# LNbits API 로 라이트닝 노드 업그레이드 하기

## LNbits 란

LNbits는 하나의 라이트닝 노드 위에서 여러 명의 지갑과 여러 개의 지갑을 관리할 수 있게 하는 `multi-user and multi-wallet management` 툴로 Umbrel을 통해서 사용할 수 있습니다. 사전에 Umbrel을 통해서 비트코인 노드와 라이트닝 노드를 설치한 후 LNbits를 설치하면, 노드 운영자의 로컬 환경에 서버 및 데이터베이스가 구축됩니다.
## LNbits 활용 방안
라이트닝 노드 위에서 여러 사용자와 여러 지갑을 만든다면 개인이 운영하는 라이트닝 노드를 체계적으로 활용할 수 있으며, 이를 더 확장하여 다른 사용자를 위해서 노드를 운영할 수 있게 됩니다. 예를 들어, 사업자가 라이트닝 네트워크를 통해 비트코인 결제를 받을 때 비즈니스의 목적이나 상점에 따라 지갑을 구분할 수 있습니다. A 라는 비즈니스를 운영하면서 a1, a2, a3 상점용 지갑을 구분할 수 있고, B 라는 비즈니스를 운영하면서 b1, b2, b3 상점용 지갑을 구분할 수 있습니다.
또한, 한 상점에서 다른 사용자를 위한 지갑을 생성함으로써 소비자를 위해서 라이트닝 지갑을 만들어 줄 수 있습니다. 이 라이트닝 지갑은 비트코인 적립 등 마케팅 목적으로 사용할 수 있으며, 소비자들이 비트코인을 더 친숙하게 사용하는데도 도움을 줄 수 있습니다. **즉, LNBits는 라이트닝 노드 운영자의 편의성을 향상시키는 툴이고, 라이트닝 노드를 여러 개 운영할 필요없이 multi-user 와 multi-wallet 관리를 가능하게 하는 툴이라고 볼 수 있습니다.**
## LNbits 동작 원리

LNbits에서 지갑은 `wallet id` 와 `admin key` 로 관리됩니다. `wallet id` 는 각 지갑마다 부여되는 고유한 값을 의미하고, 각 지갑에 대한 제어 권한은 `admin key` 단위로 관리합니다. 권한 제어를 위해 `invoice/read key` 라는 것이 별도로 있는데, 이 key 는 지갑에 대한 `admin key`처럼 모든 권한을 갖고 있는 것이 아닌 invoice 발행과 잔액 조회에 대한 접근 권한만 갖고 있습니다. 흔히 token 이라고도 불리는 API key는 쉽게 이해하기 위해서는 사용자 아이디와 패스워드의 조합과 같은 역할을 합니다.

여러 사용자와 지갑을 생성하기 위해서는 LNbits 에서 `User Manager` extension 을 설치해야 합니다. LNbits 는 다양한 종류의 extension 을 적용할 수 있도록 되어 있는데, 그 기능 중 `User Manager` 를 설치해야지 라이트닝 노드 아래 multi-user, multi-wallet 체계를 만들 수 있게 합니다.
`User Manager` 에서 사용자와 지갑을 생성하는 방법은 2가지가 있습니다. 첫 번째 방법은 LNbits의 인터페이스에서 제공하는 `Add wallet` 버튼을 통해서 생성할 수 있습니다. 두 번째 방법은 API 를 통해서 생성할 수 있습니다. API 에 대한 설명은 웹페이지의 우측에 설명이 되어 있고, 자세한 설명을 보기 위해서는 Swagger 로 생성된 API Documentation 문서를 보면 알 수 있습니다. API 를 통해서 사용자와 지갑을 생성하게 된다면 개인 홈페이지에서 사용자의 지갑을 만들어 줄 수 있게 됩니다.

사용자들이 생성한 지갑을 자신의 Blue Wallet 이나 Zeus 와 같이 핸드폰에서 사용하기 위해서는 LNbits에서 `LndHub` extension을 설치해야 합니다. `LndHub`를 설치하면 어떻게 import 하는 방법이 나와있고, 이 가이드에 따라서 라이트닝 지갑에 LNbits에서 생성한 지갑을 import 할 수 있습니다.
여기서 주의해야 할 점은 외부 사용자에게 QR 코드 또는 URL 을 통해서 오픈하기 위해서는 **노드가 운영되는 서버에 대한 외부 접근이 허용**되어야 합니다. 기본적으로 LNbits 에서 제공하는 URL 은 localhost 와 같이 로컬 환경에서의 URL 만 제공하기 때문에 localhost 부분을 `website.me` 로 대체하여 외부에 노출해야지 사용가능합니다. 이 부분은 LNbits를 벗어난 내용이므로 다루지 않겠습니다.
## LNbits 주의사항
LNbits 를 사용할 때 주의해야 할 사항이 두가지가 있습니다. 첫 번째, LNbits 에서 사용하는 지갑은 비트코인 네트워크나 라이트닝 네트워크와 관련이 없습니다. 비트코인 네트워크로 트랜잭션을 발생시키거나 라이트닝 채널을 여는 작업은 LNbits 와는 관련이 없습니다. LNbits 는 노드 운영 시 생산성을 위한 툴로, 하나의 노드 안에서 데이터베이스와 API 로만 구성되어 있습니다.
두 번째, LNbits 에서 생성한 user id 와 wallet id 는 기억하고 있어야 합니다. LNbits 의 메인 페이지에서 user id 와 wallet id 가 보이지 않기 때문에 이 정보가 없어지면 잔액이나 인보이스 생성에 대한 기능을 사용하지 못합니다. 따라서, 메모장 같은 곳에 user id 와 wallet id 를 기록했다가 `http://localhost:3007/wallet?usr=abc&wal=def` 와 같이 URL로 접근해야 합니다. 혹여나 사용자 정보와 지갑 정보를 잊어버렸다고 해도 라이트닝 노드의 잔고 총액은 변하지 않고 입출금을 할 수 있기 때문에 걱정할 필요는 없습니다. 다만, 그 사용자와 지갑에 대한 디테일한 잔고 정보만 없어지는 것이라고 볼 수 있습니다.
## LNbits API 설명
API 설명에 앞서 제가 어떤 기능을 구현했는지 먼저 살펴보겠습니다. **첫 번째, 내 라이트닝 노드에서 다른 사람들의 지갑을 자동 생성하기, 두 번째, 발행된 지갑으로 랜덤 사토시 지급하기**를 구현했습니다.
### 1. 라이트닝 노드에서 다른 사람들의 지갑을 생성하기
사전 준비
- 비트코인 노드 설치
- 라이트닝 노드 설치
- LNbits 설치
- LNbits > User Manager 설치
- LNbits > LndHub 설치
- LndHub 를 통해 접근할 수 있도록 외부로 API 노출
사전 준비가 끝났으면, LNbits > User Manager 를 들어갑니다. 우측을 보면 API 에 대한 사용법이 적혀져 있습니다. 이 중 `POST user + initial wallet` 를 선택하면 관련된 API 들이 나옵니다. 구체적인 설명은 생략하고 코드로 보면, `/usermanager/api/v1/users` 라는 REST API 를 활용하여 필요한 `admin_id`, `user_name`, `wallet_name` 인자들을 임의로 지정해주고, headers `X-Api-Key`, 즉 `admin key` 를 입력하여 REST API 를 호출해줍니다.
```python=
api = os.environ["LNBITS_URL"] + "/usermanager/api/v1/users"
params = {"admin_id": os.environ["LNBITS_ADMIN_ID"], "user_name": username, "wallet_name": walletname}
headers = {"X-Api-Key": os.environ["LNBITS_ADMIN_API_KEY"]}
response = requests.post(api, headers=headers, json=params)
```

반환값이 201이면 정상적으로 생성이 된 것이고, 외부의 사용자에게 지갑 import 를 허용시키기 위해서는 `lndhub url` 를 제공해줘야 합니다. 이 때, localhost 는 외부에서 볼 수 없는 주소이기 때문에 `lndhub://admin:{adminkey}@https://website.me/lndhub/ext/` 값으로 lndhub url 을 QR 코드 또는 URL 형태로 제공해줘야 합니다.
### 2. 생성된 지갑으로 랜덤 사토시 지급하기
생성된 지갑으로 랜덤 사토시를 지급하기 위해서는 지갑에서 인보이스를 생성하고, 생성된 인보이스를 통해서 treasury 가 송금하도록 해야 합니다. 먼저, 인보이스를 생성하는 코드를 보면 아래와 같습니다.
```python=
api = os.environ["LNBITS_URL"] + "/api/v1/payments"
headers = {"X-Api-Key": userApiKey}
params = {"out": False, "amount": sats, "memo": "giving away random sats", "unit": "sat", "lnurl_callback": True}
response = requests.post(api, headers=headers, json=params)
```
`/api/v1/payments` API 를 활용하고, 인자로는 입금용 인보이스인지 (out), 얼만큼을 받을건지 (sats), 단위는 사토시인지 (unit) 를 명시해줍니다. 여기서 headers 에 usrApiKey 를 넣어주는데, 이 값이 사용자의 지갑마다 부여된 `admin key` 라고 볼 수 있습니다.
그 다음으로, 인보이스로 송금하는 코드는 아래와 같습니다.
```python=
api = os.environ["LNBITS_URL"] + "/api/v1/payments"
headers = {"X-Api-Key": userApiKey}
params = {"out": True, "bolt11": bolt11, "memo": f"pay {sats} sats to {walletname}"}
response = requests.post(api, headers=headers, json=params)
```
여기서는 인보이스 발급과 동일한 API 를 사용하는데, 다른 점은 out 변수가 True 로 송금 목적임을 설정하고 있고, bolt11 이라는 변수를 넣어줍니다. bolt11 은 인보이스를 성공적으로 발급받았을 때 갖고 있는 값으로, 이 값을 기억하고 있다가 보낼 때 bolt11 변수에 넣어주면 됩니다.

### 마치며
LNbits 를 개인 라이트닝 노드에서 사용하는 것을 넘어서 외부로 공개하는 단계로 나아가는 것은 생각보다 작업해야 하는 부분이 많습니다. 외부에서 랜덤 사토시를 마구 받아가지 못하기 위한 방어 코드나 lndhub 를 외부로 노출시키기 위한 작업들은 LNbits 를 넘어선 이야기인 것 같아 여기에 자세히 적지는 않았습니다. 여유가 좀 된다면 조금 더 자세한 내용까지 다뤄보도록 하겠습니다 :rocket: