├── tests ├── __init__.py ├── conftest.py ├── utils.py └── test_integration.py ├── requirements.txt ├── client ├── NotFound.html ├── main.js ├── toast.js ├── Json.html ├── QR.html ├── LuaCode.html ├── EventRow.html ├── List.html ├── MultiField.html ├── Markdown.html ├── Call.html ├── Create.html ├── App.html ├── accountStore.js ├── Home.html ├── Account.html ├── View.html └── Docs.html ├── static ├── bet.png ├── icon.png ├── lnurlpayicon.png ├── Inconsolata-Bold.ttf ├── terms.txt ├── index.html ├── rings.svg └── global.css ├── .babelrc ├── .gitignore ├── pytest.ini ├── runlua ├── helpers.go ├── keybase.go ├── contract_lua_functions.go ├── cmd │ └── main.go └── runlua.go ├── package.json ├── Makefile ├── admin.go ├── rollup.config.js ├── account_functions.go ├── go.mod ├── stream.go ├── types └── types.go ├── contract_functions.go ├── postgres.sql ├── lightning.go ├── helpers.go ├── call_handlers.go ├── payment_receive.go ├── contract_handlers.go ├── lnurlpay.go ├── github.go ├── main.go ├── call_functions.go └── account_handlers.go /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pytest 2 | pylightning 3 | bitcoin-requests 4 | sseclient-py 5 | -------------------------------------------------------------------------------- /client/NotFound.html: -------------------------------------------------------------------------------- 1 | Page not found! 2 | 3 | go back to home! 4 | -------------------------------------------------------------------------------- /static/bet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melvincarvalho/etleneum/master/static/bet.png -------------------------------------------------------------------------------- /static/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melvincarvalho/etleneum/master/static/icon.png -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env", 4 | "@babel/preset-react" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /static/lnurlpayicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melvincarvalho/etleneum/master/static/lnurlpayicon.png -------------------------------------------------------------------------------- /static/Inconsolata-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/melvincarvalho/etleneum/master/static/Inconsolata-Bold.ttf -------------------------------------------------------------------------------- /client/main.js: -------------------------------------------------------------------------------- 1 | /** @format */ 2 | 3 | import App from './App.html' 4 | 5 | const app = new App({ 6 | target: document.getElementById('app') 7 | }) 8 | 9 | export default app 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.env 2 | *.swp 3 | *.swo 4 | etleneum 5 | node_modules 6 | lib 7 | bindata.go 8 | .merlin 9 | venv 10 | __pycache__ 11 | browserify-cache.json 12 | runcall 13 | static/*bundle* 14 | .pyre 15 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | testpaths = tests 3 | log_cli = true 4 | log_cli_level = DEBUG 5 | log_cli_date_format = %H:%M:%S 6 | log_cli_format = %(asctime)s %(levelname)s %(message)s 7 | addopts = -s -vv -x --show-capture=no 8 | -------------------------------------------------------------------------------- /static/terms.txt: -------------------------------------------------------------------------------- 1 | Terms of Service 2 | 3 | All satoshis sent to this website are to be considered donations. 4 | Any functionality that allows you to withdraw satoshis from this website can be suspended at any time. 5 | 6 | Privacy Policy 7 | 8 | The only data that is collected is the data you send during method calls that is shown publicly on the website. 9 | Identities aren't represented internally by anything else than the public key supplied by your authentication agent and the short id shown in the website. 10 | -------------------------------------------------------------------------------- /client/toast.js: -------------------------------------------------------------------------------- 1 | /** @format */ 2 | 3 | import Toastify from 'toastify-js' 4 | 5 | function toast(type, html, duration) { 6 | Toastify({ 7 | text: html, 8 | duration: 7000, 9 | close: duration > 10000, 10 | gravity: 'top', 11 | positionLeft: false, 12 | className: `toast-${type}` 13 | }).showToast() 14 | } 15 | 16 | export const info = (html, d = 7000) => toast('info', html, d) 17 | export const warning = (html, d = 7000) => toast('warning', html, d) 18 | export const error = (html, d = 7000) => toast('error', html, d) 19 | export const success = (html, d = 7000) => toast('success', html, d) 20 | -------------------------------------------------------------------------------- /runlua/helpers.go: -------------------------------------------------------------------------------- 1 | package runlua 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | var reNumber = regexp.MustCompile("\\d+") 11 | 12 | func stackTraceWithCode(stacktrace string, code string) string { 13 | var result []string 14 | 15 | stlines := strings.Split(stacktrace, "\n") 16 | lines := strings.Split(code, "\n") 17 | // result = append(result, stlines[0]) 18 | 19 | for i := 0; i < len(stlines); i++ { 20 | stline := stlines[i] 21 | result = append(result, stline) 22 | 23 | snum := reNumber.FindString(stline) 24 | if snum != "" { 25 | num, _ := strconv.Atoi(snum) 26 | for i, line := range lines { 27 | line = fmt.Sprintf("%3d %s", i+1, line) 28 | if i+1 > num-3 && i+1 < num+3 { 29 | result = append(result, line) 30 | } 31 | } 32 | } 33 | } 34 | 35 | return strings.Join(result, "\n") 36 | } 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@rollup/plugin-commonjs": "^11.0.2", 4 | "@rollup/plugin-inject": "^4.0.1", 5 | "@rollup/plugin-json": "^4.0.2", 6 | "@rollup/plugin-node-resolve": "^7.1.1", 7 | "prettier-plugin-svelte": "^0.7.0", 8 | "rollup": "^2.2.0", 9 | "rollup-plugin-shim": "^1.0.0", 10 | "rollup-plugin-svelte": "^5.1.1", 11 | "rollup-plugin-terser": "^4.0.4", 12 | "svelte": "^3.20.1" 13 | }, 14 | "dependencies": { 15 | "bech32": "^1.1.3", 16 | "buffer": "^5.5.0", 17 | "dom-json-tree": "^1.0.7", 18 | "flua": "^0.2.2", 19 | "highlight.js": "^9.18.1", 20 | "hmac": "^1.0.1", 21 | "kjua": "^0.6.0", 22 | "markdown-it": "^10.0.0", 23 | "promise-window": "^1.2.1", 24 | "punycode": "^2.1.1", 25 | "sha.js": "^2.4.11", 26 | "svelte-spa-router": "^1.3.0", 27 | "toastify-js": "^1.7.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: etleneum runcall 2 | 3 | etleneum: $(shell find . -name "*.go") bindata.go 4 | go build -ldflags="-s -w" -o ./etleneum 5 | 6 | runcall: runlua/runlua.go runlua/cmd/main.go 7 | cd runlua/cmd && go build -o ../../runcall 8 | 9 | bindata.go: static/bundle.js static/index.html static/global.css static/bundle.css 10 | go-bindata -o bindata.go static/... 11 | 12 | static/bundle.js: $(shell find client) 13 | ./node_modules/.bin/rollup -c 14 | 15 | deploy_test: etleneum 16 | ssh root@nusakan-58 'systemctl stop etleneum-test' 17 | scp etleneum nusakan-58:etleneum-test/etleneum 18 | ssh root@nusakan-58 'systemctl start etleneum-test' 19 | 20 | deploy: etleneum 21 | scp etleneum aspidiske-402:.lightning/plugins/etleneum-new 22 | ssh aspidiske-402 'lightning/cli/lightning-cli plugin stop etleneum; mv .lightning/plugins/etleneum-new .lightning/plugins/etleneum; lightning/cli/lightning-cli plugin start $$HOME/.lightning/plugins/etleneum' 23 | -------------------------------------------------------------------------------- /static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | etleneum 11 | 12 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 34 | -------------------------------------------------------------------------------- /client/Json.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41 | 42 |
43 | -------------------------------------------------------------------------------- /admin.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/sha256" 5 | "encoding/hex" 6 | "fmt" 7 | "net/http" 8 | 9 | "github.com/gorilla/mux" 10 | ) 11 | 12 | func handleDecodeScid(w http.ResponseWriter, r *http.Request) { 13 | scid := mux.Vars(r)["scid"] 14 | 15 | uscid, err := decodeShortChannelId(scid) 16 | if err != nil { 17 | http.Error(w, err.Error(), 400) 18 | return 19 | } 20 | 21 | callid, ok := parseShortChannelId(uscid) 22 | if !ok { 23 | http.Error(w, "couldn't parse, not a call id.", 400) 24 | return 25 | } 26 | 27 | returnCallDetails(w, callid) 28 | } 29 | 30 | func handleCallDetails(w http.ResponseWriter, r *http.Request) { 31 | callid := mux.Vars(r)["callid"] 32 | returnCallDetails(w, callid) 33 | } 34 | 35 | func returnCallDetails(w http.ResponseWriter, callid string) { 36 | scid := makeShortChannelId(callid) 37 | preimage := makePreimage(callid) 38 | hash := sha256.Sum256(preimage) 39 | 40 | fmt.Fprintf(w, ` 41 | call: %s 42 | short_channel_id: %s 43 | preimage: %s 44 | hash: %s 45 | 46 | `, callid, 47 | encodeShortChannelId(scid), 48 | hex.EncodeToString(preimage), 49 | hex.EncodeToString(hash[:]), 50 | ) 51 | } 52 | -------------------------------------------------------------------------------- /client/QR.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 38 | 39 | 52 | 53 |
54 | 55 | 56 |
57 | -------------------------------------------------------------------------------- /client/LuaCode.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 28 | 29 | 44 | 45 | 46 | 49 | 50 |
51 |   
52 |     
53 |   
54 | 
55 |
56 |  
57 |   
58 | 
59 | -------------------------------------------------------------------------------- /client/EventRow.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 34 | 35 |
36 |
37 |
38 | {#if call.contract_id !== contract}{call.contract_id} 41 | /{/if} {call.id} 42 |
43 |
{call.time.split('T').join(' ').replace(/\..*/, '')}
44 |
{call.caller || ''}
45 |
46 |
47 |
{call.method}({parseInt(call.msatoshi/1000)}sat)
48 | 49 |
50 | 51 | {#each call.transfers as transfer} 52 | 53 | 54 | 55 | 56 | 57 | {/each} 58 |
{parseInt(transfer.msatoshi/1000)}sat{transfer.direction === 'out' ? 'to' : 'from'}{transfer.counterparty}
59 |
60 | -------------------------------------------------------------------------------- /client/List.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 19 | 20 | 42 | 43 |
44 | {#if !contracts} 45 |
loading
46 | {:else} {#each contracts as ct} 47 |
48 |

{ct.name}

49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
id{ct.id}
satoshi{parseInt(ct.funds / 1000)}
calls{ct.ncalls}
63 |
64 | {/each} {/if} 65 |
66 | -------------------------------------------------------------------------------- /client/MultiField.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 44 | 45 | 54 | 55 |
56 | 57 | {#if type == 'text-line'} 58 | 59 | {:else if type == 'text-area'} 60 |