feat(@desktop/wallet): Multichain QR Code

Implements the new Recieve Modal with multichain functionality

closes #5735, #6057
This commit is contained in:
Khushboo Mehta 2022-05-18 23:58:07 +02:00 committed by Khushboo-dev-cpp
parent 56f7c52e81
commit 8d3fad8342
29 changed files with 373 additions and 109 deletions

View File

@ -12,6 +12,9 @@ type
nativeCurrencySymbol: string nativeCurrencySymbol: string
isTest: bool isTest: bool
isEnabled: bool isEnabled: bool
iconUrl: string
chainColor: string
shortName: string
proc initItem*( proc initItem*(
chainId: int, chainId: int,
@ -24,6 +27,9 @@ proc initItem*(
nativeCurrencySymbol: string, nativeCurrencySymbol: string,
isTest: bool, isTest: bool,
isEnabled: bool, isEnabled: bool,
iconUrl: string,
chainColor: string,
shortName: string,
): Item = ): Item =
result.chainId = chainId result.chainId = chainId
result.nativeCurrencyDecimals = nativeCurrencyDecimals result.nativeCurrencyDecimals = nativeCurrencyDecimals
@ -35,6 +41,9 @@ proc initItem*(
result.nativeCurrencySymbol = nativeCurrencySymbol result.nativeCurrencySymbol = nativeCurrencySymbol
result.isTest = isTest result.isTest = isTest
result.isEnabled = isEnabled result.isEnabled = isEnabled
result.iconUrl = iconUrl
result.chainColor = chainColor
result.shortName = shortName
proc `$`*(self: Item): string = proc `$`*(self: Item): string =
result = fmt"""NetworkItem( result = fmt"""NetworkItem(
@ -46,8 +55,11 @@ proc `$`*(self: Item): string =
blockExplorerURL:{self.blockExplorerURL}, blockExplorerURL:{self.blockExplorerURL},
nativeCurrencyName:{self.nativeCurrencyName}, nativeCurrencyName:{self.nativeCurrencyName},
nativeCurrencySymbol:{self.nativeCurrencySymbol}, nativeCurrencySymbol:{self.nativeCurrencySymbol},
isTest:{self.isTest} isTest:{self.isTest},
isEnabled:{self.isEnabled} isEnabled:{self.isEnabled},
iconUrl:{self.iconUrl},
shortName: {self.shortName},
chainColor: {self.chainColor},
]""" ]"""
proc getChainId*(self: Item): int = proc getChainId*(self: Item): int =
@ -79,3 +91,12 @@ proc getIsTest*(self: Item): bool =
proc getIsEnabled*(self: Item): bool = proc getIsEnabled*(self: Item): bool =
return self.isEnabled return self.isEnabled
proc getIconURL*(self: Item): string =
return self.iconUrl
proc getShortName*(self: Item): string =
return self.shortName
proc getChainColor*(self: Item): string =
return self.chainColor

View File

@ -14,6 +14,9 @@ type
NativeCurrencySymbol NativeCurrencySymbol
IsTest IsTest
IsEnabled IsEnabled
IconUrl
ChainColor
ShortName
QtObject: QtObject:
type type
@ -59,6 +62,9 @@ QtObject:
ModelRole.NativeCurrencySymbol.int:"nativeCurrencySymbol", ModelRole.NativeCurrencySymbol.int:"nativeCurrencySymbol",
ModelRole.IsTest.int:"isTest", ModelRole.IsTest.int:"isTest",
ModelRole.IsEnabled.int:"isEnabled", ModelRole.IsEnabled.int:"isEnabled",
ModelRole.IconUrl.int:"iconUrl",
ModelRole.ShortName.int: "shortName",
ModelRole.ChainColor.int: "chainColor",
}.toTable }.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant = method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -92,6 +98,12 @@ QtObject:
result = newQVariant(item.getIsTest()) result = newQVariant(item.getIsTest())
of ModelRole.IsEnabled: of ModelRole.IsEnabled:
result = newQVariant(item.getIsEnabled()) result = newQVariant(item.getIsEnabled())
of ModelRole.IconUrl:
result = newQVariant(item.getIconURL())
of ModelRole.ShortName:
result = newQVariant(item.getShortName())
of ModelRole.ChainColor:
result = newQVariant(item.getChainColor())
proc setItems*(self: Model, items: seq[Item]) = proc setItems*(self: Model, items: seq[Item]) =
self.beginResetModel() self.beginResetModel()

View File

@ -80,6 +80,9 @@ QtObject:
n.nativeCurrencySymbol, n.nativeCurrencySymbol,
n.isTest, n.isTest,
n.enabled, n.enabled,
n.iconUrl,
n.chainColor,
n.shortName,
)) ))
self.layer1.setItems(items.filter(i => i.getLayer() == 1)) self.layer1.setItems(items.filter(i => i.getLayer() == 1))
self.layer2.setItems(items.filter(i => i.getLayer() == 2)) self.layer2.setItems(items.filter(i => i.getLayer() == 2))

View File

@ -115,7 +115,9 @@ let NETWORKS* = %* [
"chainName": "Mainnet", "chainName": "Mainnet",
"rpcUrl": "https://mainnet.infura.io/v3/" & INFURA_TOKEN_RESOLVED, "rpcUrl": "https://mainnet.infura.io/v3/" & INFURA_TOKEN_RESOLVED,
"blockExplorerUrl": "https://etherscan.io/", "blockExplorerUrl": "https://etherscan.io/",
"iconUrl": "", "iconUrl": "network/Network=Ethereum",
"chainColor": "#627EEA",
"shortName": "eth",
"nativeCurrencyName": "Ether", "nativeCurrencyName": "Ether",
"nativeCurrencySymbol": "ETH", "nativeCurrencySymbol": "ETH",
"nativeCurrencyDecimals": 18, "nativeCurrencyDecimals": 18,
@ -128,7 +130,9 @@ let NETWORKS* = %* [
"chainName": "Ropsten", "chainName": "Ropsten",
"rpcUrl": "https://ropsten.infura.io/v3/" & INFURA_TOKEN_RESOLVED, "rpcUrl": "https://ropsten.infura.io/v3/" & INFURA_TOKEN_RESOLVED,
"blockExplorerUrl": "https://ropsten.etherscan.io/", "blockExplorerUrl": "https://ropsten.etherscan.io/",
"iconUrl": "", "iconUrl": "network/Network=Tetnet",
"chainColor": "#939BA1",
"shortName": "ropEth",
"nativeCurrencyName": "Ether", "nativeCurrencyName": "Ether",
"nativeCurrencySymbol": "ETH", "nativeCurrencySymbol": "ETH",
"nativeCurrencyDecimals": 18, "nativeCurrencyDecimals": 18,
@ -141,7 +145,9 @@ let NETWORKS* = %* [
"chainName": "Rinkeby", "chainName": "Rinkeby",
"rpcUrl": "https://rinkeby.infura.io/v3/" & INFURA_TOKEN_RESOLVED, "rpcUrl": "https://rinkeby.infura.io/v3/" & INFURA_TOKEN_RESOLVED,
"blockExplorerUrl": "https://rinkeby.etherscan.io/", "blockExplorerUrl": "https://rinkeby.etherscan.io/",
"iconUrl": "", "iconUrl": "network/Network=Tetnet",
"chainColor": "#939BA1",
"shortName": "rinEth",
"nativeCurrencyName": "Ether", "nativeCurrencyName": "Ether",
"nativeCurrencySymbol": "ETH", "nativeCurrencySymbol": "ETH",
"nativeCurrencyDecimals": 18, "nativeCurrencyDecimals": 18,
@ -154,7 +160,9 @@ let NETWORKS* = %* [
"chainName": "Goerli", "chainName": "Goerli",
"rpcUrl": "http://goerli.blockscout.com/", "rpcUrl": "http://goerli.blockscout.com/",
"blockExplorerUrl": "https://goerli.etherscan.io/", "blockExplorerUrl": "https://goerli.etherscan.io/",
"iconUrl": "", "iconUrl": "network/Network=Tetnet",
"chainColor": "#939BA1",
"shortName": "goeEth",
"nativeCurrencyName": "Ether", "nativeCurrencyName": "Ether",
"nativeCurrencySymbol": "ETH", "nativeCurrencySymbol": "ETH",
"nativeCurrencyDecimals": 18, "nativeCurrencyDecimals": 18,
@ -167,7 +175,9 @@ let NETWORKS* = %* [
"chainName": "Optimism", "chainName": "Optimism",
"rpcUrl": "https://optimism-mainnet.infura.io/v3/" & INFURA_TOKEN_RESOLVED, "rpcUrl": "https://optimism-mainnet.infura.io/v3/" & INFURA_TOKEN_RESOLVED,
"blockExplorerUrl": "https://optimistic.etherscan.io", "blockExplorerUrl": "https://optimistic.etherscan.io",
"iconUrl": "", "iconUrl": "network/Network=Optimism",
"chainColor": "#E90101",
"shortName": "opt",
"nativeCurrencyName": "Ether", "nativeCurrencyName": "Ether",
"nativeCurrencySymbol": "ETH", "nativeCurrencySymbol": "ETH",
"nativeCurrencyDecimals": 18, "nativeCurrencyDecimals": 18,
@ -180,7 +190,9 @@ let NETWORKS* = %* [
"chainName": "Optimism Kovan", "chainName": "Optimism Kovan",
"rpcUrl": "https://optimism-kovan.infura.io/v3/" & INFURA_TOKEN_RESOLVED, "rpcUrl": "https://optimism-kovan.infura.io/v3/" & INFURA_TOKEN_RESOLVED,
"blockExplorerUrl": "https://kovan-optimistic.etherscan.io", "blockExplorerUrl": "https://kovan-optimistic.etherscan.io",
"iconUrl": "", "iconUrl": "network/Network=Tetnet",
"chainColor": "#939BA1",
"shortName": "kovOpt",
"nativeCurrencyName": "Ether", "nativeCurrencyName": "Ether",
"nativeCurrencySymbol": "ETH", "nativeCurrencySymbol": "ETH",
"nativeCurrencyDecimals": 18, "nativeCurrencyDecimals": 18,
@ -193,7 +205,9 @@ let NETWORKS* = %* [
"chainName": "Arbitrum", "chainName": "Arbitrum",
"rpcUrl": "https://arbitrum-mainnet.infura.io/v3/" & INFURA_TOKEN_RESOLVED, "rpcUrl": "https://arbitrum-mainnet.infura.io/v3/" & INFURA_TOKEN_RESOLVED,
"blockExplorerUrl": "https://arbiscan.io/", "blockExplorerUrl": "https://arbiscan.io/",
"iconUrl": "", "iconUrl": "network/Network=Arbitrum",
"chainColor": "#51D0F0",
"shortName": "arb",
"nativeCurrencyName": "Ether", "nativeCurrencyName": "Ether",
"nativeCurrencySymbol": "ETH", "nativeCurrencySymbol": "ETH",
"nativeCurrencyDecimals": 18, "nativeCurrencyDecimals": 18,
@ -206,7 +220,9 @@ let NETWORKS* = %* [
"chainName": "Arbitrum Rinkeby", "chainName": "Arbitrum Rinkeby",
"rpcUrl": "https://arbitrum-rinkeby.infura.io/v3/" & INFURA_TOKEN_RESOLVED, "rpcUrl": "https://arbitrum-rinkeby.infura.io/v3/" & INFURA_TOKEN_RESOLVED,
"blockExplorerUrl": " https://testnet.arbiscan.io", "blockExplorerUrl": " https://testnet.arbiscan.io",
"iconUrl": "", "iconUrl": "network/Network=Tetnet",
"chainColor": "#939BA1",
"shortName": "rinArb",
"nativeCurrencyName": "Ether", "nativeCurrencyName": "Ether",
"nativeCurrencySymbol": "ETH", "nativeCurrencySymbol": "ETH",
"nativeCurrencyDecimals": 18, "nativeCurrencyDecimals": 18,

View File

@ -15,9 +15,25 @@ type NetworkDto* = ref object
nativeCurrencySymbol* {.serializedFieldName("nativeCurrencySymbol").}: string nativeCurrencySymbol* {.serializedFieldName("nativeCurrencySymbol").}: string
isTest* {.serializedFieldName("isTest").}: bool isTest* {.serializedFieldName("isTest").}: bool
enabled* {.serializedFieldName("enabled").}: bool enabled* {.serializedFieldName("enabled").}: bool
chainColor* {.serializedFieldName("chainColor").}: string
shortName* {.serializedFieldName("shortName").}: string
proc `$`*(self: NetworkDto): string = proc `$`*(self: NetworkDto): string =
return fmt"Network(chainId:{self.chainId}, name:{self.chainName}, rpcURL:{self.rpcURL}, isTest:{self.isTest}, enabled:{self.enabled})" return fmt"""Network(
chainId:{self.chainId},
nativeCurrencyDecimals:{self.nativeCurrencyDecimals},
layer:{self.layer},
chainName:{self.chainName},
name:{self.chainName},
rpcURL:{self.rpcURL},
blockExplorerURL:{self.blockExplorerURL},
iconURL:{self.iconURL},
nativeCurrencyName:{self.nativeCurrencyName},
nativeCurrencySymbol:{self.nativeCurrencySymbol},
isTest:{self.isTest}, enabled:{self.enabled},
chainColor:{self.chainColor},
shortName:{self.shortName}
)"""
proc hash*(self: NetworkDto): Hash = proc hash*(self: NetworkDto): Hash =
return self.chainId.hash return self.chainId.hash

View File

@ -69,6 +69,8 @@ proc upsertNetwork*(self: Service, network: NetworkDto) =
nativeCurrencySymbol: network.nativeCurrencySymbol, nativeCurrencySymbol: network.nativeCurrencySymbol,
isTest: network.isTest, isTest: network.isTest,
enabled: network.enabled, enabled: network.enabled,
chainColor: network.chainColor,
shortName: network.shortName,
)) ))
self.dirty.store(true) self.dirty.store(true)

View File

@ -38,7 +38,8 @@ type
nativeCurrencySymbol* {.serializedFieldName("nativeCurrencySymbol").}: string nativeCurrencySymbol* {.serializedFieldName("nativeCurrencySymbol").}: string
isTest* {.serializedFieldName("isTest").}: bool isTest* {.serializedFieldName("isTest").}: bool
enabled* {.serializedFieldName("enabled").}: bool enabled* {.serializedFieldName("enabled").}: bool
chainColor* {.serializedFieldName("chainColor").}: string
shortName* {.serializedFieldName("shortName").}: string
rpc(clientVersion, "web3"): rpc(clientVersion, "web3"):
discard discard

View File

@ -7,7 +7,7 @@ import StatusQ.Core.Theme 0.1
StatusListItem { StatusListItem {
property var network property var network
title: network.chainName title: network.chainName
image.source: Style.png("networks/" + network.chainName.toLowerCase()) image.source: Style.png(network.iconUrl)
width: parent.width width: parent.width
leftPadding: Style.current.padding leftPadding: Style.current.padding
rightPadding: Style.current.padding rightPadding: Style.current.padding

View File

@ -59,6 +59,13 @@ Popup {
delegate: chainItem delegate: chainItem
} }
StatusBaseText {
font.pixelSize: Style.current.primaryTextFontSize
color: Theme.palette.baseColor1
text: qsTr("Layer 2")
visible: chainRepeater2.count > 0
}
Repeater { Repeater {
id: chainRepeater2 id: chainRepeater2
model: popup.layer2Networks model: popup.layer2Networks
@ -77,22 +84,16 @@ Popup {
Component { Component {
id: chainItem id: chainItem
Item { StatusListItem {
width: content.width implicitWidth: scrollView.width
height: 40 title: model.chainName
StatusBaseText { image.source: Style.png(model.iconUrl)
anchors.left: parent.left onClicked: {
anchors.leftMargin: Style.current.bigPadding checkBox.checked = !checkBox.checked
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: Style.current.primaryTextFontSize
text: model.chainName
color: Theme.palette.directColor1
} }
components: [
StatusCheckBox { StatusCheckBox {
anchors.right: parent.right id: checkBox
anchors.rightMargin: Style.current.bigPadding
anchors.verticalCenter: parent.verticalCenter
checked: model.isEnabled checked: model.isEnabled
onCheckedChanged: { onCheckedChanged: {
if (model.isEnabled !== checked) { if (model.isEnabled !== checked) {
@ -100,6 +101,7 @@ Popup {
} }
} }
} }
]
} }
} }
} }

View File

@ -1,12 +1,15 @@
import QtQuick 2.13 import QtQuick 2.13
import QtQuick.Controls 2.13 import QtQuick.Controls 2.13
import QtGraphicalEffects 1.13 import QtGraphicalEffects 1.13
import QtQuick.Layouts 1.13
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import StatusQ.Popups 0.1 import StatusQ.Popups 0.1
import StatusQ.Components 0.1 import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Core.Utils 0.1
import utils 1.0 import utils 1.0
@ -17,25 +20,147 @@ import "../stores"
StatusModal { StatusModal {
id: popup id: popup
property alias selectedAccount: accountSelector.selectedAccount property var selectedAccount
property string networkPrefix: ""
property string completeAddressWithNetworkPrefix
onSelectedAccountChanged: {
if (selectedAccount.address) {
txtWalletAddress.text = selectedAccount.address
}
}
onCompleteAddressWithNetworkPrefixChanged: {
qrCodeImage.source = RootStore.getQrCode(completeAddressWithNetworkPrefix)
}
//% "Receive" //% "Receive"
header.title: qsTrId("receive") header.title: qsTrId("receive")
contentHeight: layout.implicitHeight contentHeight: layout.implicitHeight
width: 556 width: 556
showHeader: false
showAdvancedHeader: true
hasFloatingButtons: true
advancedHeaderComponent: StatusFloatingButtonsSelector {
id: floatingHeader
model: RootStore.accounts
delegate: Rectangle {
width: button.width
height: button.height
radius: 8
visible: floatingHeader.visibleIndices.includes(index)
StatusButton {
id: button
topPadding: 8
bottomPadding: 0
implicitHeight: 32
defaultLeftPadding: 4
text: name
icon.emoji: !!emoji ? emoji: ""
icon.emojiSize: Emoji.size.middle
icon.name: !emoji ? "filled-account": ""
normalColor: "transparent"
highlighted: index === floatingHeader.currentIndex
onClicked: {
popup.selectedAccount = model
floatingHeader.currentIndex = index
}
Component.onCompleted: {
// On startup make the preseected wallet in the floating menu
if(name === popup.selectedAccount.name)
floatingHeader.currentIndex = index
}
}
}
popupMenuDelegate: StatusListItem {
implicitWidth: 272
title: name
subTitle: currencyBalance
icon.emoji: !!emoji ? emoji: ""
icon.color: model.color
icon.name: !emoji ? "filled-account": ""
icon.letterSize: 14
icon.isLetterIdenticon: !!model.emoji
icon.background.color: Theme.palette.indirectColor1
onClicked: {
popup.selectedAccount = model
floatingHeader.itemSelected(index)
}
visible: !floatingHeader.visibleIndices.includes(index)
}
}
contentItem: Column { contentItem: Column {
id: layout id: layout
width: popup.width width: popup.width
topPadding: Style.current.smallPadding topPadding: Style.current.xlPadding
spacing: Style.current.bigPadding spacing: Style.current.bigPadding
StatusSwitchTabBar {
id: tabBar
anchors.horizontalCenter: parent.horizontalCenter
StatusSwitchTabButton {
text: qsTr("Legacy")
}
StatusSwitchTabButton {
text: qsTr("Multichain")
enabled: localAccountSensitiveSettings.isMultiNetworkEnabled
}
}
Item {
width: parent.width
height: qrCodeBox.height
id: centralLayout
Grid {
id: multiChainList
property bool need2Columns: RootStore.enabledNetworks.count >= 9
anchors.centerIn: parent
anchors.horizontalCenterOffset: need2Columns ? 0 : qrCodeBox.width/2 + Style.current.xlPadding + Style.current.halfPadding
height: qrCodeBox.height
columnSpacing: need2Columns ? qrCodeBox.width + Style.current.bigPadding : 0
flow: Grid.TopToBottom
columns: need2Columns ? 2 : 1
spacing: 5
Repeater {
model: RootStore.enabledNetworks
delegate: StatusListItemTag {
image.source: Style.png(iconUrl)
title: shortName
titleText.color: chainColor
closeButtonVisible: false
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: selectPopup.open()
}
}
}
StatusListItemTag {
closeButtonVisible: false
icon.name: "edit_pencil"
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
selectPopup.open()
}
}
}
}
Rectangle { Rectangle {
id: qrCodeBox id: qrCodeBox
anchors.horizontalCenter: parent.horizontalCenter
height: 339 height: 339
width: 339 width: 339
anchors.centerIn: parent
anchors.horizontalCenter: parent.horizontalCenter
layer.enabled: true layer.enabled: true
layer.effect: OpacityMask { layer.effect: OpacityMask {
maskSource: Item { maskSource: Item {
@ -90,23 +215,6 @@ StatusModal {
} }
} }
} }
StatusAccountSelector {
id: accountSelector
anchors.horizontalCenter: parent.horizontalCenter
width: 240
label: ""
showAccountDetails: false
accounts: RootStore.accounts
currency: RootStore.currentCurrency
dropdownWidth: parent.width - (Style.current.padding * 2)
dropdownAlignment: StatusSelect.MenuAlignment.Center
onSelectedAccountChanged: {
if (selectedAccount.address) {
qrCodeImage.source = RootStore.getQrCode(selectedAccount.address)
txtWalletAddress.text = selectedAccount.address
}
}
} }
Item { Item {
@ -124,6 +232,23 @@ StatusModal {
color: Theme.palette.baseColor1 color: Theme.palette.baseColor1
text: qsTr("Your Address") text: qsTr("Your Address")
} }
RowLayout {
id: networksLabel
spacing: -1
Repeater {
model: RootStore.enabledNetworks
delegate: StatusBaseText {
font.pixelSize: 15
color: chainColor
text: shortName + ":"
Component.onCompleted: {
if(index === 0)
popup.networkPrefix = ""
popup.networkPrefix +=text
}
}
}
}
StatusAddress { StatusAddress {
id: txtWalletAddress id: txtWalletAddress
color: Theme.palette.directColor1 color: Theme.palette.directColor1
@ -137,6 +262,7 @@ StatusModal {
anchors.rightMargin: Style.current.bigPadding anchors.rightMargin: Style.current.bigPadding
spacing: 5 spacing: 5
CopyToClipBoardButton { CopyToClipBoardButton {
id: copyToClipBoard
store: RootStore store: RootStore
textToCopy: txtWalletAddress.text textToCopy: txtWalletAddress.text
} }
@ -148,6 +274,71 @@ StatusModal {
} }
} }
} }
NetworkSelectPopup {
id: selectPopup
x: multiChainList.x + Style.current.xlPadding + Style.current.halfPadding
y: centralLayout.y
layer1Networks: RootStore.layer1Networks
layer2Networks: RootStore.layer2Networks
testNetworks: RootStore.testNetworks
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
onToggleNetwork: {
RootStore.toggleNetwork(chainId)
}
}
states: [
State {
name: "legacy"
when: tabBar.currentIndex === 0
PropertyChanges {
target: multiChainList
visible: false
}
PropertyChanges {
target: contactsLabel
visible: true
}
PropertyChanges {
target: networksLabel
visible: false
}
PropertyChanges {
target: copyToClipBoard
textToCopy: txtWalletAddress.text
}
PropertyChanges {
target: popup
completeAddressWithNetworkPrefix: popup.selectedAccount.address
}
},
State {
name: "multichain"
when: tabBar.currentIndex === 1
PropertyChanges {
target: multiChainList
visible: true
}
PropertyChanges {
target: contactsLabel
visible: false
}
PropertyChanges {
target: networksLabel
visible: true
}
PropertyChanges {
target: copyToClipBoard
textToCopy: popup.networkPrefix + txtWalletAddress.text
}
PropertyChanges {
target: popup
completeAddressWithNetworkPrefix: popup.networkPrefix + popup.selectedAccount.address
}
}
]
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit efa14805bd3a87f7e87f2655dd651dc4d9c18e6d Subproject commit fea37ff5b46ff84153591d327f4672b7d3c45915