# rgb-proxy-server — Developer Reference

> **Source:** https://github.com/RGB-Tools/rgb-proxy-server
> **Docker:** `ghcr.io/rgb-tools/rgb-proxy-server`
> **Protocol spec:** https://github.com/RGB-Tools/rgb-http-json-rpc
> **Part of:** github.com/RGB-Tools — official higher-level projects for RGB Protocol on Bitcoin v0.11.1

The RGB proxy server relays consignment files between RGB wallets. It implements the RGB HTTP JSON-RPC protocol and is the **primary transport method for RGB asset transfers in production**.

---

## What it does

In RGB Protocol, asset transfers require exchanging off-chain data (consignment files) between the payer and the payee. The proxy server acts as an intermediary:

1. Payer creates transfer and **posts the consignment** to the proxy (using the payee's blinded UTXO as identifier)
2. Payee **fetches the consignment** by blinded UTXO
3. Payee validates the consignment locally (client-side)
4. Payee **posts ACK** (valid) or **NACK** (invalid)
5. Payer checks ACK/NACK — if ACK, broadcasts the Bitcoin transaction with the commitment

The proxy server does **not validate asset state** and does **not need to be trusted**. Anyone can self-host an instance. Users concerned about censorship can switch providers.

---

## Run

### Locally (Node.js)

```sh
# Install dependencies
npm install

# Development mode (port 3000, auto-reload)
npm run dev

# Production
npm run build
npm run start
```

### Docker

```sh
# Basic run
docker run -d ghcr.io/rgb-tools/rgb-proxy-server

# With persistent data (recommended for production)
docker run -d \
  -v /host/path:/home/node/.rgb-proxy-server \
  ghcr.io/rgb-tools/rgb-proxy-server
# Note: /host/path must be owned by user:group 1000
```

### Data storage

Default: `$HOME/.rgb-proxy-server`  
Override: set `APP_DATA` environment variable

---

## API (JSON-RPC over HTTP)

All requests go to: `POST http://<host>:<port>/json-rpc`  
Content-Type: `application/json` (for JSON body) or `multipart/form-data` (for file upload)

---

### `consignment.post` — Payer posts consignment

```sh
curl -X POST -H 'Content-Type: multipart/form-data' \
  -F 'jsonrpc=2.0' \
  -F 'id="1"' \
  -F 'method=consignment.post' \
  -F 'params[recipient_id]=<blinded_utxo>' \
  -F 'params[txid]=<txid>' \
  -F 'file=@consignment.rgb' \
  http://localhost:3000/json-rpc
```

Response:
```json
{"jsonrpc":"2.0","id":"1","result":true}
```

---

### `consignment.get` — Payee fetches consignment

```sh
curl -X POST -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":"2","method":"consignment.get","params":{"recipient_id":"<blinded_utxo>"}}' \
  http://localhost:3000/json-rpc
```

Response:
```json
{
  "jsonrpc": "2.0",
  "id": "2",
  "result": {
    "consignment": "<base64-encoded-binary>",
    "txid": "<txid>"
  }
}
```

Decode the consignment:
```sh
echo '<base64-string>' | base64 -d > consignment.rgb
```

---

### `ack.post` — Payee posts ACK or NACK

ACK (consignment is valid):
```sh
curl -X POST -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":"3","method":"ack.post","params":{"recipient_id":"<blinded_utxo>","ack":true}}' \
  http://localhost:3000/json-rpc
```

NACK (consignment is invalid):
```sh
curl -X POST -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":"4","method":"ack.post","params":{"recipient_id":"<blinded_utxo>","ack":false}}' \
  http://localhost:3000/json-rpc
```

Response:
```json
{"jsonrpc":"2.0","id":"3","result":true}
```

---

### `ack.get` — Payer checks ACK status

```sh
curl -X POST -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":"5","method":"ack.get","params":{"recipient_id":"<blinded_utxo>"}}' \
  http://localhost:3000/json-rpc
```

Response:
- `true` — payee sent ACK (payer can broadcast transaction)
- `false` — payee sent NACK (transfer failed, start over)
- `null` — payee has not posted yet (payer should retry later)

---

## Public proxy endpoints

For testing (testnet), the Iris Wallet team runs a public proxy:

- Testnet3: `rpcs://proxy.iriswallet.com/0.2/json-rpc`
- Testnet4: `rpcs://proxy.iriswallet.com/0.2/json-rpc` (same endpoint)

For production (mainnet), **self-host** or use an agreed provider.

---

## Integration with rgb-lib

When calling `go_online` in rgb-lib, pass the proxy endpoint:

```rust
let online = wallet.go_online(
    false,
    "ssl://electrum.iriswallet.com:50013".to_string(),  // indexer
)?;
// proxy endpoint is set in WalletData or via transport endpoint in invoice
```

In rgb-lib invoices, the transport endpoint encodes the proxy URL:

```
rgb:Tk3d0h5w-.../~/BF/bcrt:utxob:...
```

The proxy URL used for a specific transfer is included in the invoice string via the transport endpoint parameter.

---

## Integration with rgb-lightning-node

When unlocking an RLN node, provide the proxy endpoint:

```json
{
  "proxy_endpoint": "rpc://127.0.0.1:3000/json-rpc"
}
```

For testnet:
```json
{
  "proxy_endpoint": "rpcs://proxy.iriswallet.com/0.2/json-rpc"
}
```

---

## Canonical sources

- https://github.com/RGB-Tools/rgb-proxy-server — repository
- https://github.com/RGB-Tools/rgb-http-json-rpc — protocol specification
- https://docs.rgb.info — RGB Protocol technical documentation