parent
ac75f0ed00
commit
a2c1730486
|
@ -168,3 +168,5 @@ type
|
|||
MessageTimeout,
|
||||
SubprotocolReason = 0x10
|
||||
|
||||
proc `$`*(v: Capability): string =
|
||||
v.name & '/' & $v.version
|
||||
|
|
|
@ -1338,6 +1338,9 @@ proc rlpxConnect*(node: EthereumNode, remote: Node): Future[Peer] {.async.} =
|
|||
|
||||
await postHelloSteps(result, response)
|
||||
ok = true
|
||||
info "Peer connected",
|
||||
enode=result.remote.node,
|
||||
capabilities=result.network.capabilities
|
||||
except PeerDisconnected as e:
|
||||
if e.reason != TooManyPeers:
|
||||
debug "Unexpected disconnect during rlpxConnect", reason = e.reason
|
||||
|
@ -1415,6 +1418,9 @@ proc rlpxAccept*(node: EthereumNode,
|
|||
result.remote = newNode(initEnode(handshake.remoteHPubkey, address))
|
||||
|
||||
await postHelloSteps(result, response)
|
||||
info "Peer accepted",
|
||||
enode=result.remote.node,
|
||||
capabilities=result.network.capabilities
|
||||
except PeerDisconnected as e:
|
||||
if e.reason == AlreadyConnected:
|
||||
debug "Disconnect during rlpxAccept", reason = e.reason
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
DOtherSide/
|
||||
docker
|
||||
*.AppImage
|
||||
*.qmlc
|
||||
tmp/
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/sh
|
||||
|
||||
rm -rf DOtherSide
|
||||
git clone https://github.com/filcuc/DOtherSide.git --depth=1
|
||||
cd DOtherSide
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=${1:-.} ..
|
||||
make -j4 DOtherSideStatic
|
|
@ -0,0 +1,23 @@
|
|||
#!/bin/sh
|
||||
|
||||
[ -f docker/nim/bin/nim ] || {
|
||||
mkdir -p docker
|
||||
cd docker
|
||||
git clone https://github.com/status-im/nim.git --depth 1
|
||||
cd nim
|
||||
sh build_all.sh
|
||||
bin/nim c -d:release -o:bin/nimble dist/nimble/src/nimble
|
||||
cd ../..
|
||||
}
|
||||
|
||||
sudo apt-get install -y cmake
|
||||
|
||||
export PATH=$PATH:$PWD/docker/nim/bin
|
||||
export PKG_CONFIG_PATH=/opt/qt/5.12.0/gcc_64/lib/pkgconfig
|
||||
export LD_LIBRARY_PATH=/opt/qt/5.12.0/gcc_64/lib/
|
||||
|
||||
cd ../..
|
||||
nimble develop
|
||||
cd examples/stratus
|
||||
|
||||
make clean appimage
|
|
@ -0,0 +1,35 @@
|
|||
const
|
||||
# bootnodes taken from go-ethereum
|
||||
MainBootnodes* = [
|
||||
"enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303",
|
||||
"enode://3f1d12044546b76342d59d4a05532c14b85aa669704bfe1f864fe079415aa2c02d743e03218e57a33fb94523adb54032871a6c51b2cc5514cb7c7e35b3ed0a99@13.93.211.84:30303",
|
||||
"enode://78de8a0916848093c73790ead81d1928bec737d565119932b98c6b100d944b7a95e94f847f689fc723399d2e31129d182f7ef3863f2b4c820abbf3ab2722344d@191.235.84.50:30303",
|
||||
"enode://158f8aab45f6d19c6cbf4a089c2670541a8da11978a2f90dbf6a502a4a3bab80d288afdbeb7ec0ef6d92de563767f3b1ea9e8e334ca711e9f8e2df5a0385e8e6@13.75.154.138:30303",
|
||||
"enode://1118980bf48b0a3640bdba04e0fe78b1add18e1cd99bf22d53daac1fd9972ad650df52176e7c7d89d1114cfef2bc23a2959aa54998a46afcf7d91809f0855082@52.74.57.123:30303",
|
||||
"enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303",
|
||||
]
|
||||
# Whisper nodes taken from:
|
||||
# https://github.com/status-im/status-react/blob/80aa0e92864c638777a45c3f2aeb66c3ae7c0b2e/resources/config/fleets.json
|
||||
# These are probably not on the main network?
|
||||
WhisperNodes* = [
|
||||
"enode://66ba15600cda86009689354c3a77bdf1a97f4f4fb3ab50ffe34dbc904fac561040496828397be18d9744c75881ffc6ac53729ddbd2cdbdadc5f45c400e2622f7@206.189.243.176:30305",
|
||||
"enode://0440117a5bc67c2908fad94ba29c7b7f2c1536e96a9df950f3265a9566bf3a7306ea8ab5a1f9794a0a641dcb1e4951ce7c093c61c0d255f4ed5d2ed02c8fce23@35.224.15.65:30305",
|
||||
"enode://a80eb084f6bf3f98bf6a492fd6ba3db636986b17643695f67f543115d93d69920fb72e349e0c617a01544764f09375bb85f452b9c750a892d01d0e627d9c251e@47.89.16.125:30305",
|
||||
"enode://4ea35352702027984a13274f241a56a47854a7fd4b3ba674a596cff917d3c825506431cf149f9f2312a293bb7c2b1cca55db742027090916d01529fe0729643b@206.189.243.178:30305",
|
||||
"enode://552942cc4858073102a6bcd0df9fe4de6d9fc52ddf7363e8e0746eba21b0f98fb37e8270bc629f72cfe29e0b3522afaf51e309a05998736e2c0dad5288991148@130.211.215.133:30305",
|
||||
"enode://aa97756bc147d74be6d07adfc465266e17756339d3d18591f4be9d1b2e80b86baf314aed79adbe8142bcb42bc7bc40e83ee3bbd0b82548e595bf855d548906a1@47.52.188.241:30305",
|
||||
"enode://ce559a37a9c344d7109bd4907802dd690008381d51f658c43056ec36ac043338bd92f1ac6043e645b64953b06f27202d679756a9c7cf62fdefa01b2e6ac5098e@206.189.243.179:30305",
|
||||
"enode://b33dc678589931713a085d29f9dc0efee1783dacce1d13696eb5d3a546293198470d97822c40b187336062b39fd3464e9807858109752767d486ea699a6ab3de@35.193.151.184:30305",
|
||||
"enode://f34451823b173dc5f2ac0eec1668fdb13dba9452b174249a7e0272d6dce16fb811a01e623300d1b7a67c240ae052a462bff3f60e4a05e4c4bd23cc27dea57051@47.52.173.66:30305",
|
||||
"enode://4e0a8db9b73403c9339a2077e911851750fc955db1fc1e09f81a4a56725946884dd5e4d11258eac961f9078a393c45bcab78dd0e3bc74e37ce773b3471d2e29c@206.189.243.171:30305",
|
||||
"enode://eb4cc33c1948b1f4b9cb8157757645d78acd731cc8f9468ad91cef8a7023e9c9c62b91ddab107043aabc483742ac15cb4372107b23962d3bfa617b05583f2260@146.148.66.209:30305",
|
||||
"enode://7c80e37f324bbc767d890e6381854ef9985d33940285413311e8b5927bf47702afa40cd5d34be9aa6183ac467009b9545e24b0d0bc54ef2b773547bb8c274192@47.91.155.62:30305",
|
||||
"enode://a8bddfa24e1e92a82609b390766faa56cf7a5eef85b22a2b51e79b333c8aaeec84f7b4267e432edd1cf45b63a3ad0fc7d6c3a16f046aa6bc07ebe50e80b63b8c@206.189.243.172:30305",
|
||||
"enode://c7e00e5a333527c009a9b8f75659d9e40af8d8d896ebaa5dbdd46f2c58fc010e4583813bc7fc6da98fcf4f9ca7687d37ced8390330ef570d30b5793692875083@35.192.123.253:30305",
|
||||
"enode://4b2530d045b1d9e0e45afa7c008292744fe77675462090b4001f85faf03b87aa79259c8a3d6d64f815520ac76944e795cbf32ff9e2ce9ba38f57af00d1cc0568@47.90.29.122:30305",
|
||||
"enode://887cbd92d95afc2c5f1e227356314a53d3d18855880ac0509e0c0870362aee03939d4074e6ad31365915af41d34320b5094bfcc12a67c381788cd7298d06c875@206.189.243.177:30305",
|
||||
"enode://2af8f4f7a0b5aabaf49eb72b9b59474b1b4a576f99a869e00f8455928fa242725864c86bdff95638a8b17657040b21771a7588d18b0f351377875f5b46426594@35.232.187.4:30305",
|
||||
"enode://76ee16566fb45ca7644c8dec7ac74cadba3bfa0b92c566ad07bcb73298b0ffe1315fd787e1f829e90dba5cd3f4e0916e069f14e50e9cbec148bead397ac8122d@47.91.226.75:30305",
|
||||
"enode://2b01955d7e11e29dce07343b456e4e96c081760022d1652b1c4b641eaf320e3747871870fa682e9e9cfb85b819ce94ed2fee1ac458904d54fd0b97d33ba2c4a4@206.189.240.70:30305",
|
||||
"enode://19872f94b1e776da3a13e25afa71b47dfa99e658afd6427ea8d6e03c22a99f13590205a8826443e95a37eee1d815fc433af7a8ca9a8d0df7943d1f55684045b7@35.238.60.236:30305"
|
||||
]
|
|
@ -0,0 +1,142 @@
|
|||
import QtQuick 2.3
|
||||
import QtQuick.Controls 1.3
|
||||
import QtQuick.Controls 2.3
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
ApplicationWindow {
|
||||
width: 1600
|
||||
height: 1050
|
||||
title: "Stratus"
|
||||
visible: true
|
||||
|
||||
function joinChannel() {
|
||||
root.join(channelTextField.text)
|
||||
joinedChannels.append({"name": channelTextField.text})
|
||||
channelTextField.text = ""
|
||||
}
|
||||
|
||||
function sendMessage() {
|
||||
messageTextField.text = "haha. you thought this actually worked? go fix it!"
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 50; running: true; repeat: true
|
||||
onTriggered: root.onTimer()
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: joinedChannels
|
||||
// ListElement { name: "test" }
|
||||
}
|
||||
|
||||
SplitView {
|
||||
anchors.fill: parent
|
||||
orientation: Qt.Horizontal
|
||||
|
||||
Item {
|
||||
width: parent.width * 0.25
|
||||
|
||||
ColumnLayout {
|
||||
anchors.margins: 5
|
||||
anchors.fill: parent
|
||||
spacing: 5
|
||||
|
||||
ListView {
|
||||
model: joinedChannels
|
||||
Layout.fillHeight: true
|
||||
|
||||
delegate: Row {
|
||||
spacing: 0
|
||||
Text { text: name[0].toUpperCase(); font.pointSize: 24; font.bold: true; width: height ; horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter; anchors.verticalCenter: parent.verticalCenter }
|
||||
Text { text: "#"; font.pointSize: 16; verticalAlignment: Text.AlignVCenter; anchors.verticalCenter: parent.verticalCenter }
|
||||
Text { text: name; font.pointSize: 16; verticalAlignment: Text.AlignVCenter; anchors.verticalCenter: parent.verticalCenter }
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Text { text: "#"; font.pointSize: 16 }
|
||||
TextField { id: channelTextField; Layout.fillWidth: true; onAccepted: joinChannel() }
|
||||
|
||||
Button {
|
||||
id: joinButton
|
||||
text: "Join channel"
|
||||
onClicked: joinChannel()
|
||||
enabled: channelTextField.text != ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
|
||||
ColumnLayout {
|
||||
anchors.margins: 5
|
||||
anchors.fill: parent
|
||||
|
||||
ListModel {
|
||||
id: sampleMessages
|
||||
ListElement {
|
||||
channel: "test"
|
||||
source: "xxx"
|
||||
time: "1212"
|
||||
message: "message that is really really long xxxxXXXXxxsacdsca asdcasd cas cdad casd cascdsa ad sadcasd csad csad csadmessage that is really really long xxxxXXXXxxsacdsca asdcasd cas cdad casd cascdsa ad sadcasd csad csad csad"
|
||||
}
|
||||
ListElement {
|
||||
channel: "test"
|
||||
source: "xxx"
|
||||
time: "1212"
|
||||
message: "message that is really really long"
|
||||
}
|
||||
ListElement {
|
||||
channel: "test"
|
||||
source: "xxx"
|
||||
time: "1212"
|
||||
message: "message that is really really long xxxxXXXXxxsacdsca asdcasd cas cdad casd cascdsa ad sadcasd csad csad csadmessage that is really really long xxxxXXXXxxsacdsca asdcasd cas cdad casd cascdsa ad sadcasd csad csad csad"
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: messagesView
|
||||
model: root.messageList
|
||||
// model: sampleMessages
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
delegate: RowLayout {
|
||||
width: messagesView.width
|
||||
Text { text: "👾"; font.pointSize: 28 }
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
RowLayout {
|
||||
Text { text: channel; font.bold: true }
|
||||
Text { text: " ("; }
|
||||
Text { text: source; }
|
||||
Text { text: ")"; }
|
||||
Item { Layout.fillWidth: true }
|
||||
Text { text: time; }
|
||||
}
|
||||
|
||||
Text { Layout.fillWidth: true; text: message; wrapMode: Text.WordWrap }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
TextField {
|
||||
id: messageTextField;
|
||||
Layout.fillWidth: true;
|
||||
onAccepted: sendMessage()
|
||||
}
|
||||
|
||||
Button {
|
||||
id: sendButton
|
||||
text: "Send"
|
||||
onClicked: sendMessage()
|
||||
enabled: messageTextField.text != ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
import NimQml, statusmessage, Tables
|
||||
|
||||
type
|
||||
StatusMessageRoles {.pure.} = enum
|
||||
Channel = UserRole + 1
|
||||
Source = UserRole + 2
|
||||
Message = UserRole + 3
|
||||
Time = UserRole + 4
|
||||
|
||||
QtObject:
|
||||
type
|
||||
MessageList* = ref object of QAbstractListModel
|
||||
messages*: seq[StatusMessage]
|
||||
|
||||
proc delete(self: MessageList) =
|
||||
self.QAbstractListModel.delete
|
||||
for message in self.messages:
|
||||
message.delete
|
||||
self.messages = @[]
|
||||
|
||||
proc setup(self: MessageList) =
|
||||
self.QAbstractListModel.setup
|
||||
|
||||
proc newMessageList*(): MessageList =
|
||||
new(result, delete)
|
||||
result.messages = @[]
|
||||
result.setup
|
||||
|
||||
method rowCount(self: MessageList, index: QModelIndex = nil): int =
|
||||
return self.messages.len
|
||||
|
||||
method data(self: MessageList, index: QModelIndex, role: int): QVariant =
|
||||
if not index.isValid:
|
||||
return
|
||||
if index.row < 0 or index.row >= self.messages.len:
|
||||
return
|
||||
let message = self.messages[index.row]
|
||||
let messageRole = role.StatusMessageRoles
|
||||
case messageRole:
|
||||
of StatusMessageRoles.Channel: result = newQVariant(message.channel)
|
||||
of StatusMessageRoles.Source: result = newQVariant(message.source)
|
||||
of StatusMessageRoles.Message: result = newQVariant(message.message)
|
||||
of StatusMessageRoles.Time: result = newQVariant(message.time)
|
||||
else: return
|
||||
|
||||
method roleNames(self: MessageList): Table[int, string] =
|
||||
{ StatusMessageRoles.Channel.int:"channel",
|
||||
StatusMessageRoles.Source.int:"source",
|
||||
StatusMessageRoles.Message.int:"message",
|
||||
StatusMessageRoles.Time.int:"time"}.toTable
|
||||
|
||||
proc add*(
|
||||
self: MessageList, channel: string, source: string, message: string,
|
||||
time: string) {.slot.} =
|
||||
let sm = newStatusMessage(channel, source, message, time)
|
||||
|
||||
self.beginInsertRows(newQModelIndex(), self.messages.len, self.messages.len)
|
||||
self.messages.add(sm)
|
||||
self.endInsertRows()
|
||||
|
||||
proc del*(self: MessageList, pos: int) {.slot.} =
|
||||
if pos < 0 or pos >= self.messages.len:
|
||||
return
|
||||
self.beginRemoveRows(newQModelIndex(), pos, pos)
|
||||
self.messages.del(pos)
|
||||
self.endRemoveRows
|
|
@ -0,0 +1,43 @@
|
|||
import NimQml, messagelist
|
||||
|
||||
QtObject:
|
||||
type Root* = ref object of QObject
|
||||
messageList*: MessageList
|
||||
app: QApplication
|
||||
cb: proc()
|
||||
doJoin: proc(channel: string)
|
||||
|
||||
proc delete*(self: Root) =
|
||||
self.QObject.delete
|
||||
self.messageList.delete
|
||||
|
||||
proc setup(self: Root) =
|
||||
self.QObject.setup
|
||||
|
||||
proc newRoot*(
|
||||
app: QApplication, cb: proc(),
|
||||
doJoin: proc(channel: string)): Root =
|
||||
new(result)
|
||||
result.messageList = newMessageList()
|
||||
result.app = app
|
||||
result.cb = cb
|
||||
result.doJoin = doJoin
|
||||
result.setup()
|
||||
|
||||
proc getMessageList(self: Root): QVariant {.slot.} =
|
||||
return newQVariant(self.messageList)
|
||||
|
||||
proc onExitTriggered(self: Root) {.slot.} =
|
||||
self.app.quit
|
||||
|
||||
proc onTimer(self: Root) {.slot.} =
|
||||
self.cb()
|
||||
|
||||
QtProperty[QVariant] messageList:
|
||||
read = getMessageList
|
||||
|
||||
proc add*(self: var Root, a, b, c, d: string) =
|
||||
self.messageList.add(a, b, c, d)
|
||||
|
||||
proc join*(self: Root, channel: string) {.slot.} =
|
||||
self.doJoin(channel)
|
|
@ -0,0 +1,47 @@
|
|||
import NimQml
|
||||
|
||||
QtObject:
|
||||
type StatusMessage* = ref object of QObject
|
||||
channel: string
|
||||
source: string
|
||||
message: string
|
||||
time: string
|
||||
|
||||
proc delete*(self: StatusMessage) =
|
||||
self.QObject.delete
|
||||
|
||||
proc setup(self: StatusMessage) =
|
||||
self.QObject.setup
|
||||
|
||||
proc newStatusMessage*(channel, source, message, time: string): StatusMessage =
|
||||
result = StatusMessage(
|
||||
channel: channel,
|
||||
source: source,
|
||||
message: message,
|
||||
time: time,
|
||||
)
|
||||
result.setup
|
||||
|
||||
proc channel*(self: StatusMessage): string {.slot.} =
|
||||
self.channel
|
||||
|
||||
QtProperty[string] channel:
|
||||
read = channel
|
||||
|
||||
proc source*(self: StatusMessage): string {.slot.} =
|
||||
self.source
|
||||
|
||||
QtProperty[string] source:
|
||||
read = source
|
||||
|
||||
proc message*(self: StatusMessage): string {.slot.} =
|
||||
self.message
|
||||
|
||||
QtProperty[string] message:
|
||||
read = message
|
||||
|
||||
proc time*(self: StatusMessage): string {.slot.} =
|
||||
self.time
|
||||
|
||||
QtProperty[string] time:
|
||||
read = time
|
|
@ -0,0 +1,6 @@
|
|||
docker run -it --rm --device /dev/fuse \
|
||||
-v /home/arnetheduck/status/nim-eth-p2p:/nim-eth-p2p:Z \
|
||||
-w /nim-eth-p2p/examples/stratus \
|
||||
--cap-add SYS_ADMIN \
|
||||
a12e/docker-qt:5.12-gcc_64 \
|
||||
sh build-in-docker.sh
|
|
@ -0,0 +1,7 @@
|
|||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Stratus
|
||||
Exec=stratus %F
|
||||
Icon=stratus
|
||||
Comment=Fun with nimbus
|
||||
Terminal=true
|
|
@ -0,0 +1,114 @@
|
|||
#
|
||||
# Ethereum P2P
|
||||
# (c) Copyright 2018
|
||||
# Status Research & Development GmbH
|
||||
#
|
||||
# Licensed under either of
|
||||
# Apache License, version 2.0, (LICENSE-APACHEv2)
|
||||
# MIT license (LICENSE-MIT)
|
||||
|
||||
import
|
||||
cligen, sequtils, options, strutils, parseopt, asyncdispatch2, json, times,
|
||||
nimcrypto/[bcmode, hmac, rijndael, pbkdf2, sha2, sysrand, utils, keccak, hash],
|
||||
eth_keys, rlp, eth_p2p, eth_p2p/rlpx_protocols/[whisper_protocol],
|
||||
eth_p2p/[discovery, enode, peer_pool], chronicles
|
||||
|
||||
import NimQml, model/root, fleets
|
||||
|
||||
{.passl: "-lDOtherSideStatic".}
|
||||
|
||||
# Normally this part is done with CMake/qmake
|
||||
{.passl: gorge("pkg-config --libs --static Qt5Core Qt5Qml Qt5Gui Qt5Quick Qt5QuickControls2 Qt5Widgets").}
|
||||
{.passl: "-Wl,-as-needed".}
|
||||
|
||||
proc `$`*(digest: SymKey): string =
|
||||
for c in digest: result &= hexChar(c.byte)
|
||||
|
||||
# Don't do this at home, you'll never get rid of ugly globals like this!
|
||||
var
|
||||
node: EthereumNode
|
||||
rootItem: Root
|
||||
|
||||
proc subscribeChannel(
|
||||
channel: string, handler: proc (msg: ReceivedMessage)) =
|
||||
var ctx: HMAC[sha256]
|
||||
var symKey: SymKey
|
||||
discard ctx.pbkdf2(channel, "", 65356, symKey)
|
||||
|
||||
let channelHash = digest(keccak256, channel)
|
||||
var topic: array[4, byte]
|
||||
for i in 0..<4:
|
||||
topic[i] = channelHash.data[i]
|
||||
|
||||
info "Subscribing to channel", channel, topic, symKey
|
||||
|
||||
discard node.subscribeFilter(newFilter(symKey = some(symKey),
|
||||
topics = @[topic]),
|
||||
handler)
|
||||
|
||||
proc handler(msg: ReceivedMessage) =
|
||||
try:
|
||||
# ["~#c4",["dcasdc","text/plain","~:public-group-user-message",
|
||||
# 154604971756901,1546049717568,[
|
||||
# "^ ","~:chat-id","nimbus-test","~:text","dcasdc"]]]
|
||||
let
|
||||
src =
|
||||
if msg.decoded.src.isSome(): $msg.decoded.src.get()
|
||||
else: ""
|
||||
payload = cast[string](msg.decoded.payload)
|
||||
data = parseJson(cast[string](msg.decoded.payload))
|
||||
channel = data.elems[1].elems[5].elems[2].str
|
||||
time = $fromUnix(data.elems[1].elems[4].num div 1000)
|
||||
message = data.elems[1].elems[0].str
|
||||
|
||||
info "adding", full=(cast[string](msg.decoded.payload))
|
||||
rootItem.add(channel, src[0..<8] & "..." & src[^8..^1], message, time)
|
||||
except:
|
||||
notice "no luck parsing", message=getCurrentExceptionMsg()
|
||||
|
||||
proc run(port: uint16 = 30303) =
|
||||
let address = Address(
|
||||
udpPort: port.Port, tcpPort: port.Port, ip: parseIpAddress("0.0.0.0"))
|
||||
|
||||
let keys = newKeyPair()
|
||||
node = newEthereumNode(keys, address, 1, nil, addAllCapabilities = false)
|
||||
node.addCapability Whisper
|
||||
|
||||
var bootnodes: seq[ENode] = @[]
|
||||
for nodeId in MainBootnodes:
|
||||
var bootnode: ENode
|
||||
discard initENode(nodeId, bootnode)
|
||||
bootnodes.add(bootnode)
|
||||
|
||||
asyncCheck node.connectToNetwork(bootnodes, true, true)
|
||||
# main network has mostly non SHH nodes, so we connect directly to SHH nodes
|
||||
for nodeId in WhisperNodes:
|
||||
var whisperENode: ENode
|
||||
discard initENode(nodeId, whisperENode)
|
||||
var whisperNode = newNode(whisperENode)
|
||||
|
||||
asyncCheck node.peerPool.connectToNode(whisperNode)
|
||||
|
||||
node.protocolState(Whisper).config.powRequirement = 0
|
||||
|
||||
let app = newQApplication()
|
||||
defer: app.delete
|
||||
|
||||
proc joinChannel(channel: string) =
|
||||
subscribeChannel(channel, handler)
|
||||
|
||||
rootItem = newRoot(app, poll, joinChannel)
|
||||
defer: rootItem.delete
|
||||
|
||||
let engine = newQQmlApplicationEngine()
|
||||
defer: engine.delete
|
||||
|
||||
let rootVariant = newQVariant(rootItem)
|
||||
defer: rootVariant.delete
|
||||
|
||||
engine.setRootContextProperty("root", rootVariant)
|
||||
engine.load("main.qml")
|
||||
|
||||
app.exec()
|
||||
|
||||
dispatch(run)
|
|
@ -0,0 +1,4 @@
|
|||
--dynliboverrideall
|
||||
-d:"chronicles_log_level=info"
|
||||
|
||||
gcc.linkerexe="g++"
|
|
@ -0,0 +1,13 @@
|
|||
mode = ScriptMode.Verbose
|
||||
|
||||
packageName = "stratus"
|
||||
version = "0.0.0.1"
|
||||
author = "Status Research & Development GmbH"
|
||||
description = "Fun with nimbus"
|
||||
license = "MIT"
|
||||
|
||||
bin = @["stratus"]
|
||||
|
||||
requires "eth_p2p",
|
||||
"nimqml",
|
||||
"cligen 0.9.18"
|
|
@ -0,0 +1 @@
|
|||
<svg width="124" height="124" xmlns="http://www.w3.org/2000/svg"><path d="M72.458 61.429c-7.431.427-12.088-1.299-19.52-.871a31.245 31.245 0 0 0-5.47.796C48.565 47.65 58.292 35.662 71.519 34.9c8.117-.467 16.23 4.53 16.67 12.642.433 7.973-5.664 13.307-15.73 13.886M52.503 89.46c-7.776.438-15.547-4.24-15.969-11.831-.415-7.462 5.427-12.454 15.07-12.996 7.118-.4 11.58 1.216 18.698.815a30.589 30.589 0 0 0 5.24-.745C74.493 77.528 65.175 88.748 52.503 89.46M62 .181C27.758.18 0 27.857 0 62s27.758 61.82 62 61.82c34.242 0 62-27.678 62-61.82C124 27.858 96.242.18 62 .18" fill="#ff9c00" fill-rule="evenodd"/></svg>
|
After Width: | Height: | Size: 607 B |
Loading…
Reference in New Issue