Skip to content

Commit

Permalink
Koalala
Browse files Browse the repository at this point in the history
  • Loading branch information
LightningK0ala committed Oct 10, 2019
0 parents commit 7096c94
Show file tree
Hide file tree
Showing 82 changed files with 14,292 additions and 0 deletions.
36 changes: 36 additions & 0 deletions .env.sample
@@ -0,0 +1,36 @@
# The node uri of your c-lightning node
# Replace NODE_URI, IP_ADDRESS and the default port number 9735 only if necessary
LN_NODE_URI=NODE_URI@IP_ADDRESS:9735

# Mongodb uri, change this if you're hosting your own database externally.
MONGO_DB_URI=mongodb://db/satoshis-place

# Lightning Charge uri
# Replace IP_ADDRESS and PORT
CHARGE_URI=http://IP_ADDRESS:PORT

# Lightning Charge websocket uri (api-token is a fixed string, don't change it)
# Replace YOUR_PASSWORD, IP_ADDRESS and the default port number 9112 only if necessary
CHARGE_WS_URI=http://api-token:YOUR_PASSWORD@IP_ADDRESS:9112/ws

# Lightning Charge auth string (api-token is a fixed string, don't change it)
# Replace YOUR_PASSWORD
CHARGE_AUTH=api-token:YOUR_PASSWORD

# If not running locally, replace localhost with your IP address or hostname.
API_URI=http://localhost:3001

# Set this to yes for maintenance party mode.
MAINTENANCE=no

# Set this to yes to automatically process orders without having to pay.
SIMULATE_PAYMENTS=no

# Set this to yes if running testnet
TESTNET=no

# (optional) Google Analytics ID
GOOGLE_ANALYTICS=

# Adjust log level (debug, info or error)
LOG_LEVEL=debug
5 changes: 5 additions & 0 deletions .gitignore
@@ -0,0 +1,5 @@
.expo
.DS_Store
**/node_modules
yarn-error.log
.next
107 changes: 107 additions & 0 deletions API.md
@@ -0,0 +1,107 @@
# API
It's possible to interact with the API directly using websockets (socket.io@^1.7.4).
Satoshi's Place API is available at [https://api.satoshis.place](https://api.satoshis.place).
If you're running this project locally, your api is at `http://localhost:3001`.

Here's a javascript snippet that shows you how to interact with it:

```
const io = require('socket.io-client')
const socket = io(API_URI)
// Listen for errors
socket.on('error', ({ message }) => {
// Requests are rate limited by IP Address at 10 requests per second.
// You might get an error returned here.
console.log(message)
})
// Wait for connection to open before setting up event listeners
socket.on('connect', a => {
console.log('API Socket connection established with id', socket.id)
// Subscribe to events
socket.on('GET_LATEST_PIXELS_RESULT', handleGetLatestPixelsResult)
socket.on('NEW_ORDER_RESULT', handleNewOrderResult)
socket.on('ORDER_SETTLED', handleOrderSettled)
socket.on('GET_SETTINGS_RESULT', handleGetSettingsResult)
})
// Here's two examples on how you send a request, the response will be
// in the callbacks above.
socket.emit('GET_LATEST_PIXELS')
socket.emit('NEW_ORDER', pixelsArray)
```

There are 3 events that you can send and 4 you can listen to, we'll go over them now. All send + receive events, except for ORDER_SETTLED, are only between a single client and the server. You socket session ID is what allows the server to know who to respond to.

### Send Events

#### `GET_LATEST_PIXELS`
Request an image uri for the latest state of the board. No data needs to be sent. The response will be received in `GET_LATEST_PIXELS_RESULT`.

#### `GET_SETTINGS`
Request settings like invoice expiry, allowed colors etc. No data needs to be sent. The response will be received in `GET_SETTINGS_RESULT`.

#### `NEW_ORDER`
When you want to draw something, send a request with this event and an array of objects like:
```
[
{
coordinates: [0, 0],
color: '#ffffff'
},
...
]
```
where `coordinates` is the x, y position in the board (min: 0, max: 1000 for both values), and `color` is one of the allowed colors received in the settings, in web hex format. Each object represents a pixel, there's a limit to the number of pixels you can submit in each order, this is determined by the `orderPixelsLimit` value in settings.

### Receive Events

All receive events have a payload in the shape of `{ data: ..., error: ... }`, if `error` is set it will be a string with a message about an error that occured. The stuff you'll care about will be in `data`.

#### `GET_LATEST_PIXELS_RESULT`
Received after making a `GET_LATEST_PIXELS` request. Contains a base64 png image uri that represents the canvas in its current state.

#### `GET_SETTINGS_RESULT`
Received after making a `GET_SETTINGS` request. Example `data` object:
```
{
boardLength: 1000,
colors: ['#ffffff', '#e4e4e4', ...],
invoiceExpiry: 600,
orderPixelsLimit: 250000,
pricePerPixel: 1
}
```
_Note: There are 16 colors available to use._

#### `NEW_ORDER_RESULT`
Received after making a successful order. Contains the generated lightning payment request which you will pay to finalize your drawing. Example `data`:
```
{
data: 'lnbc110n1pdjpn47pp5up...'
}
```
#### `ORDER_SETTLED`
This event is used to notify all users that an update has occured on the board. `data` will look like this:
```
{
image: 'data:image/png;base64,iVBOR...',
paymentRequest: 'lnbc110n1pdjpn47pp5up...',
pixelsPaintedCount: 29,
sessionId: "ck0ehHuJ0Y2fLEMBAARS" // The session id of the user who just paid, this is used in lieu of a username to display in the satoshis.place hud.
}
```

#### `BROADCAST_STATS`
This event is used to notify all users of the latest statistics about the game. `data` will look like this:
```
{
pixelsPerDay: 1636761,
transactionsPerDay: 857
}
```

## Resources
- [Web-based Socket.io Debugger](http://amritb.github.io/socketio-client-tool/#url=aHR0cHM6Ly9hcGkuc2F0b3NoaXMucGxhY2U=&opt=&events=GET_LATEST_PIXELS_RESULT,GET_SETTINGS_RESULT,NEW_ORDER_RESULT,ORDER_SETTLED,BROADCAST_STATS)
21 changes: 21 additions & 0 deletions LICENSE
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2019 Lightning K0ala

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
58 changes: 58 additions & 0 deletions README.md
@@ -0,0 +1,58 @@
# Satoshi's Place

<img src="https://i.imgur.com/XUo6fAX.jpg" width="696"/>

This is the official repository containing the source code for [satoshis.place](satoshis.place).

Satoshi's place is a Lightning Network Application (LApp) launched in May 2018 with the purpose of showcasing the viability of running a service that accepts instant, permissionless, near-free microtransactions through Bitcoin's Lightning Network.

It consists of a collaborative art board where each pixel costs 1 satoshi to paint. Pixels can be drawn over an unlimited amount of times.

## What is this for?

It's up to you. You can learn from it, hack it, extend it, run your own version of it, etc... The software is released with an MIT license and meant as a gift to the lightning community in the run-up to the first ever [Lightning Conference](https://www.thelightningconference.com/) in 2019.

## Preparation

You'll need an instance of *c-lightning* with *lightning-charge* setup somewhere you can access. Follow the c-lightning instructions [here](https://github.com/ElementsProject/lightning) and the lightning charge instructions [here](https://github.com/ElementsProject/lightning-charge).

In order to setup the database for satoshis-place, you'll need *mongo-tools* installed in your system, if you're on linux (debian) use `sudo apt install mongo-tools`, if Mac or otherwise follow [these](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/) instructions.

You also need docker installed in your system. Follow [these](https://docs.docker.com/install/) instructions.

## Setup

1. Clone the repository and run `cd satoshis.place`.
2. Enter connection details in `.env` (see `.env.sample` for a template).
3. Run `docker-compose up -d`.
4. Run `sh scripts/bootstrap.sh`.
5. Open the application in `http://localhost:3000`.

You might need to wait a couple of seconds for the application to build before the webpage shows.
Check the logs by running `docker-compose logs -f`.
If you see a cheeky monkey `Listening on *:3001 🙉` and a bunch of `PING ...` and `PONG ...` it should be good to go!

You can use the `SIMULATE_PAYMENTS` env setting to automatically execute orders by setting it to `yes` (requires restart of the api). This will allow you to draw on the canvas without having to make a lightning payment.

## Notes on the `.env` file

These are the following strings you are meant to replace:
- NODE_URI
- IP_ADDRESS
- PORT
- YOUR_PASSWORD

Also, the ports for your lightning node and charge endpoints are hardcoded to `9735` and `9112` respectively. If you need to change these go ahead.

## Testnet

To use testnet, simply setup your *c-lightning* node to use testnet, update the connection details if required and set the `TESTNET` env setting to `yes`.

## API

The API for this application is also exposed and can be interacted with directly, the documentation for this can be found [here](API.md).

## Questions?

Any questions or suggestions feel free to open an issue in this repository or reach out to me via twitter at [@LightningK0ala](https://twitter.com/LightningK0ala).

Binary file added db-init/admin/system.version.bson
Binary file not shown.
1 change: 1 addition & 0 deletions db-init/admin/system.version.metadata.json
@@ -0,0 +1 @@
{"options":{},"indexes":[{"v":1,"key":{"_id":1},"name":"_id_","ns":"admin.system.version"},{"v":{"$numberDecimal":"2"},"key":{"version":1},"name":"incompatible_with_version_32","ns":"admin.system.version"}]}
Empty file.
1 change: 1 addition & 0 deletions db-init/satoshis-place/orders.metadata.json
@@ -0,0 +1 @@
{"options":{},"indexes":[{"v":2,"key":{"_id":1},"name":"_id_","ns":"satoshis-place.orders"}]}
Binary file added db-init/satoshis-place/pixels.bson
Binary file not shown.
1 change: 1 addition & 0 deletions db-init/satoshis-place/pixels.metadata.json
@@ -0,0 +1 @@
{"options":{},"indexes":[{"v":2,"key":{"_id":1},"name":"_id_","ns":"satoshis-place.pixels"}]}
Empty file.
1 change: 1 addition & 0 deletions db-init/satoshis-place/ratelimits.metadata.json
@@ -0,0 +1 @@
{"options":{},"indexes":[{"v":2,"key":{"_id":1},"name":"_id_","ns":"satoshis-place.ratelimits"}]}
Binary file added db-init/satoshis-place/settings.bson
Binary file not shown.
1 change: 1 addition & 0 deletions db-init/satoshis-place/settings.metadata.json
@@ -0,0 +1 @@
{"options":{},"indexes":[{"v":2,"key":{"_id":1},"name":"_id_","ns":"satoshis-place.settings"}]}
10 changes: 10 additions & 0 deletions docker-compose.override.yml
@@ -0,0 +1,10 @@
version: '3.3'
services:
api:
volumes:
- ./packages/api:/app
- /app/node_modules
web:
volumes:
- ./packages/web:/app
- /app/node_modules
44 changes: 44 additions & 0 deletions docker-compose.yml
@@ -0,0 +1,44 @@
version: '3.3'
services:
api:
restart: always
build:
context: ./packages/api
container_name: api
environment:
- MAINTENANCE=${MAINTENANCE}
- LOG_LEVEL=${LOG_LEVEL}
- SIMULATE_PAYMENTS=${SIMULATE_PAYMENTS}
- PORT=3001
- CHARGE_URI=${CHARGE_URI}
- CHARGE_WS_URI=${CHARGE_WS_URI}
- CHARGE_AUTH=${CHARGE_AUTH}
- MONGO_DB_URI=${MONGO_DB_URI}
links:
- db
ports:
- "3001:3001"
web:
restart: always
build:
context: ./packages/web
container_name: web
environment:
- MAINTENANCE=${MAINTENANCE}
- PORT=3000
- LN_NODE_URI=${LN_NODE_URI}
- TESTNET=${TESTNET}
- GOOGLE_ANALYTICS=${GOOGLE_ANALYTICS}
- API_URI=${API_URI}
links:
- api
ports:
- "3000:3000"
db:
restart: always
container_name: db
image: mongo:3.4.6
ports:
- 27017:27017
volumes:
- ~/satoshis-place-db-data:/data/db
1 change: 1 addition & 0 deletions packages/api/.gitignore
@@ -0,0 +1 @@
node_modules
18 changes: 18 additions & 0 deletions packages/api/Dockerfile
@@ -0,0 +1,18 @@
# Ubuntu + Node.js
FROM node:8.11.2

# Create app directory and set as working directory
RUN mkdir -p /app
WORKDIR /app

# Add lock file and package.json
ADD yarn.lock package.json ./

# Install dependencies
RUN yarn

# Copy app source
ADD . /app

# Run app
ENTRYPOINT ["npm", "start"]
38 changes: 38 additions & 0 deletions packages/api/package.json
@@ -0,0 +1,38 @@
{
"name": "satoshis-place-api",
"version": "0.1.0",
"main": "src/index.js",
"license": "MIT",
"scripts": {
"test": "jest",
"test:watch": "jest --watchAll",
"dev": "nodemon --exec 'node .'",
"start": "node .",
"alias": "now alias",
"alias:testnet": "now alias --local-config ./now.testnet.json",
"deploy": "now",
"deploy:testnet": "now --local-config ./now.testnet.json"
},
"dependencies": {
"64": "^0.2.0",
"bmp-js": "^0.1.0",
"fast-png": "^3.1.0",
"got": "^8.3.1",
"just-pick": "^1.0.3",
"just-safe-get": "^1.2.1",
"loglevel": "^1.6.1",
"micro": "^9.1.4",
"mongoose": "^5.0.13",
"pretty-hrtime": "^1.0.3",
"socket.io": "^1.7.4",
"ws": "^5.1.1"
},
"devDependencies": {
"faker": "^4.1.0",
"jest": "^22.4.3",
"nodemon": "^1.17.2",
"request-promise": "^4.2.2",
"socket.io-client": "^1.7.4",
"test-listen": "^1.1.0"
}
}
28 changes: 28 additions & 0 deletions packages/api/src/config/index.js
@@ -0,0 +1,28 @@
module.exports = {
// AppService length determines the square length of the board, in pixels. The
// total number of pixels in the board will be n^2.
BOARD_LENGTH: 1000, // Represents a total of 4 pixels

// Reddit Place Color Swatch
// WARNING: It's really dangerous to change these. Unexpected behavior might
// occur if this doesn't exactly match the api colors, even if it seems the
// colors passed through settings from the api are mapped.
COLOR_SWATCH: [
'#ffffff',
'#e4e4e4',
'#888888',
'#222222',
'#e4b4ca',
'#d4361e',
'#db993e',
'#8e705d',
'#e6d84e',
'#a3dc67',
'#4aba38',
'#7fcbd0',
'#5880a8',
'#3919d1',
'#c27ad0',
'#742671'
]
}

0 comments on commit 7096c94

Please sign in to comment.