mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-23 03:58:49 +00:00
feat: add support for purchased sticker packs
This commit is contained in:
parent
0a2ea90117
commit
69ba3c4468
@ -40,15 +40,18 @@ proc init*(self: ChatController) =
|
|||||||
let currAcct = status_wallet.getWalletAccounts()[0] # TODO: make generic
|
let currAcct = status_wallet.getWalletAccounts()[0] # TODO: make generic
|
||||||
let currAddr = parseAddress(currAcct.address)
|
let currAddr = parseAddress(currAcct.address)
|
||||||
|
|
||||||
let installedStickerPacks = self.status.chat.getInstalledStickerPacks(currAddr)
|
let installedStickerPacks = self.status.chat.getInstalledStickerPacks()
|
||||||
|
|
||||||
|
let purchasedStickerPacks = self.status.chat.getPurchasedStickerPacks(currAddr)
|
||||||
|
|
||||||
# TODO: getting available stickers should be done in a separate thread as there
|
# TODO: getting available stickers should be done in a separate thread as there
|
||||||
# a long wait for contract response, decoded, downloading from IPFS, EDN decoding,
|
# a long wait for contract response, decoded, downloading from IPFS, EDN decoding,
|
||||||
# etc
|
# etc
|
||||||
let availableStickerPacks = self.status.chat.getAvailableStickerPacks(currAddr)
|
let availableStickerPacks = self.status.chat.getAvailableStickerPacks()
|
||||||
for packId, stickerPack in availableStickerPacks.pairs:
|
for packId, stickerPack in availableStickerPacks.pairs:
|
||||||
let isInstalled = installedStickerPacks.hasKey(packId)
|
let isInstalled = installedStickerPacks.hasKey(packId)
|
||||||
self.view.addStickerPackToList(stickerPack, isInstalled)
|
let isBought = purchasedStickerPacks.contains(packId)
|
||||||
|
self.view.addStickerPackToList(stickerPack, isInstalled, isBought)
|
||||||
|
|
||||||
let recentStickers = self.status.chat.getRecentStickers()
|
let recentStickers = self.status.chat.getRecentStickers()
|
||||||
for sticker in recentStickers:
|
for sticker in recentStickers:
|
||||||
|
@ -48,8 +48,8 @@ QtObject:
|
|||||||
result.recentStickers = newStickerList()
|
result.recentStickers = newStickerList()
|
||||||
result.setup()
|
result.setup()
|
||||||
|
|
||||||
proc addStickerPackToList*(self: ChatsView, stickerPack: StickerPack, isInstalled: bool) =
|
proc addStickerPackToList*(self: ChatsView, stickerPack: StickerPack, isInstalled, isBought: bool) =
|
||||||
self.stickerPacks.addStickerPackToList(stickerPack, newStickerList(stickerPack.stickers), isInstalled)
|
self.stickerPacks.addStickerPackToList(stickerPack, newStickerList(stickerPack.stickers), isInstalled, isBought)
|
||||||
|
|
||||||
proc getStickerPackList(self: ChatsView): QVariant {.slot.} =
|
proc getStickerPackList(self: ChatsView): QVariant {.slot.} =
|
||||||
newQVariant(self.stickerPacks)
|
newQVariant(self.stickerPacks)
|
||||||
|
@ -12,9 +12,10 @@ type
|
|||||||
Stickers = UserRole + 6
|
Stickers = UserRole + 6
|
||||||
Thumbnail = UserRole + 7
|
Thumbnail = UserRole + 7
|
||||||
Installed = UserRole + 8
|
Installed = UserRole + 8
|
||||||
|
Bought = UserRole + 9
|
||||||
|
|
||||||
type
|
type
|
||||||
StickerPackView* = tuple[pack: StickerPack, stickers: StickerList, installed: bool]
|
StickerPackView* = tuple[pack: StickerPack, stickers: StickerList, installed, bought: bool]
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
type
|
type
|
||||||
@ -50,6 +51,7 @@ QtObject:
|
|||||||
of StickerPackRoles.Stickers: result = newQVariant(packInfo.stickers)
|
of StickerPackRoles.Stickers: result = newQVariant(packInfo.stickers)
|
||||||
of StickerPackRoles.Thumbnail: result = newQVariant(decodeContentHash(stickerPack.thumbnail))
|
of StickerPackRoles.Thumbnail: result = newQVariant(decodeContentHash(stickerPack.thumbnail))
|
||||||
of StickerPackRoles.Installed: result = newQVariant(packInfo.installed)
|
of StickerPackRoles.Installed: result = newQVariant(packInfo.installed)
|
||||||
|
of StickerPackRoles.Bought: result = newQVariant(packInfo.bought)
|
||||||
|
|
||||||
method roleNames(self: StickerPackList): Table[int, string] =
|
method roleNames(self: StickerPackList): Table[int, string] =
|
||||||
{
|
{
|
||||||
@ -60,7 +62,8 @@ QtObject:
|
|||||||
StickerPackRoles.Preview.int: "preview",
|
StickerPackRoles.Preview.int: "preview",
|
||||||
StickerPackRoles.Stickers.int: "stickers",
|
StickerPackRoles.Stickers.int: "stickers",
|
||||||
StickerPackRoles.Thumbnail.int: "thumbnail",
|
StickerPackRoles.Thumbnail.int: "thumbnail",
|
||||||
StickerPackRoles.Installed.int: "installed"
|
StickerPackRoles.Installed.int: "installed",
|
||||||
|
StickerPackRoles.Bought.int: "bought"
|
||||||
}.toTable
|
}.toTable
|
||||||
|
|
||||||
|
|
||||||
@ -82,9 +85,9 @@ QtObject:
|
|||||||
raise newException(ValueError, "Sticker pack list does not have a pack with id " & $packId)
|
raise newException(ValueError, "Sticker pack list does not have a pack with id " & $packId)
|
||||||
result = self.packs.filterIt(it.pack.id == packId)[0].pack
|
result = self.packs.filterIt(it.pack.id == packId)[0].pack
|
||||||
|
|
||||||
proc addStickerPackToList*(self: StickerPackList, pack: StickerPack, stickers: StickerList, installed: bool) =
|
proc addStickerPackToList*(self: StickerPackList, pack: StickerPack, stickers: StickerList, installed, bought: bool) =
|
||||||
self.beginInsertRows(newQModelIndex(), 0, 0)
|
self.beginInsertRows(newQModelIndex(), 0, 0)
|
||||||
self.packs.insert((pack: pack, stickers: stickers, installed: installed), 0)
|
self.packs.insert((pack: pack, stickers: stickers, installed: installed, bought: bought), 0)
|
||||||
self.endInsertRows()
|
self.endInsertRows()
|
||||||
|
|
||||||
proc removeStickerPackFromList*(self: StickerPackList, packId: int) =
|
proc removeStickerPackFromList*(self: StickerPackList, packId: int) =
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import eventemitter, json, strutils, sequtils, tables, chronicles
|
import eventemitter, json, strutils, sequtils, tables, chronicles, sugar
|
||||||
import libstatus/chat as status_chat
|
import libstatus/chat as status_chat
|
||||||
import libstatus/stickers as status_stickers
|
import libstatus/stickers as status_stickers
|
||||||
import libstatus/types
|
import libstatus/types
|
||||||
@ -38,6 +38,7 @@ type
|
|||||||
recentStickers*: seq[Sticker]
|
recentStickers*: seq[Sticker]
|
||||||
availableStickerPacks*: Table[int, StickerPack]
|
availableStickerPacks*: Table[int, StickerPack]
|
||||||
installedStickerPacks*: Table[int, StickerPack]
|
installedStickerPacks*: Table[int, StickerPack]
|
||||||
|
purchasedStickerPacks*: seq[int]
|
||||||
|
|
||||||
MessageArgs* = ref object of Args
|
MessageArgs* = ref object of Args
|
||||||
id*: string
|
id*: string
|
||||||
@ -54,6 +55,7 @@ proc newChatModel*(events: EventEmitter): ChatModel =
|
|||||||
result.recentStickers = @[]
|
result.recentStickers = @[]
|
||||||
result.availableStickerPacks = initTable[int, StickerPack]()
|
result.availableStickerPacks = initTable[int, StickerPack]()
|
||||||
result.installedStickerPacks = initTable[int, StickerPack]()
|
result.installedStickerPacks = initTable[int, StickerPack]()
|
||||||
|
result.purchasedStickerPacks = @[]
|
||||||
|
|
||||||
|
|
||||||
proc delete*(self: ChatModel) =
|
proc delete*(self: ChatModel) =
|
||||||
@ -93,29 +95,35 @@ proc join*(self: ChatModel, chatId: string, chatType: ChatType) =
|
|||||||
|
|
||||||
self.events.emit("channelJoined", ChannelArgs(chat: chat))
|
self.events.emit("channelJoined", ChannelArgs(chat: chat))
|
||||||
|
|
||||||
proc getInstalledStickerPacks*(self: ChatModel, address: EthAddress): Table[int, StickerPack] =
|
proc getPurchasedStickerPacks*(self: ChatModel, address: EthAddress): seq[int] =
|
||||||
|
if self.purchasedStickerPacks != @[]:
|
||||||
|
return self.purchasedStickerPacks
|
||||||
|
|
||||||
|
var balance = status_stickers.getBalance(address)
|
||||||
|
# balance = 2 # hardcode to test support of purchased sticker packs, because buying sticker packs is proving very difficult on testnet
|
||||||
|
var tokenIds = toSeq[0..<balance].map(idx => status_stickers.tokenOfOwnerByIndex(address, idx))
|
||||||
|
# tokenIds = @[1, 2] # hardcode to test support of purchased sticker packs
|
||||||
|
self.purchasedStickerPacks = tokenIds.map(tokenId => status_stickers.getPackIdFromTokenId(tokenId))
|
||||||
|
result = self.purchasedStickerPacks
|
||||||
|
|
||||||
|
proc getInstalledStickerPacks*(self: ChatModel): Table[int, StickerPack] =
|
||||||
if self.installedStickerPacks != initTable[int, StickerPack]():
|
if self.installedStickerPacks != initTable[int, StickerPack]():
|
||||||
return self.installedStickerPacks
|
return self.installedStickerPacks
|
||||||
|
|
||||||
# TODO: needs more fleshing out to determine which sticker packs
|
|
||||||
# we own -- owned sticker packs will simply allowed them to be installed
|
|
||||||
discard status_stickers.getBalance(address)
|
|
||||||
|
|
||||||
self.installedStickerPacks = status_stickers.getInstalledStickerPacks()
|
self.installedStickerPacks = status_stickers.getInstalledStickerPacks()
|
||||||
result = self.installedStickerPacks
|
result = self.installedStickerPacks
|
||||||
|
|
||||||
proc getAvailableStickerPacks*(self: ChatModel, address: EthAddress): Table[int, StickerPack] =
|
proc getAvailableStickerPacks*(self: ChatModel): Table[int, StickerPack] =
|
||||||
if self.availableStickerPacks != initTable[int, StickerPack]():
|
if self.availableStickerPacks != initTable[int, StickerPack]():
|
||||||
return self.availableStickerPacks
|
return self.availableStickerPacks
|
||||||
|
|
||||||
# TODO: needs more fleshing out to determine which sticker packs
|
|
||||||
# we own -- owned sticker packs will simply allowed them to be installed
|
|
||||||
discard status_stickers.getBalance(address)
|
|
||||||
|
|
||||||
let numPacks = status_stickers.getPackCount()
|
let numPacks = status_stickers.getPackCount()
|
||||||
for i in 0..<numPacks:
|
for i in 0..<numPacks:
|
||||||
|
try:
|
||||||
let stickerPack = status_stickers.getPackData(i)
|
let stickerPack = status_stickers.getPackData(i)
|
||||||
self.availableStickerPacks[stickerPack.id] = stickerPack
|
self.availableStickerPacks[stickerPack.id] = stickerPack
|
||||||
|
except:
|
||||||
|
continue
|
||||||
result = self.availableStickerPacks
|
result = self.availableStickerPacks
|
||||||
|
|
||||||
proc getRecentStickers*(self: ChatModel): seq[Sticker] =
|
proc getRecentStickers*(self: ChatModel): seq[Sticker] =
|
||||||
|
@ -23,6 +23,7 @@ type
|
|||||||
FixedBytes* [N: static[int]] = distinct array[N, byte]
|
FixedBytes* [N: static[int]] = distinct array[N, byte]
|
||||||
DynamicBytes* [N: static[int]] = distinct array[N, byte]
|
DynamicBytes* [N: static[int]] = distinct array[N, byte]
|
||||||
Address* = distinct EthAddress
|
Address* = distinct EthAddress
|
||||||
|
EncodeResult* = tuple[dynamic: bool, data: string]
|
||||||
# Bool* = distinct Int256 # TODO: implement Bool as FixedBytes[N]?
|
# Bool* = distinct Int256 # TODO: implement Bool as FixedBytes[N]?
|
||||||
|
|
||||||
type PackData* = object
|
type PackData* = object
|
||||||
@ -40,7 +41,12 @@ let CONTRACTS: seq[Contract] = @[
|
|||||||
("transfer", Method(signature: "transfer(address,uint256)"))
|
("transfer", Method(signature: "transfer(address,uint256)"))
|
||||||
].toTable
|
].toTable
|
||||||
),
|
),
|
||||||
Contract(name: "snt", network: Network.Testnet, address: parseAddress("0xc55cf4b03948d7ebc8b9e8bad92643703811d162")),
|
Contract(name: "snt", network: Network.Testnet, address: parseAddress("0xc55cf4b03948d7ebc8b9e8bad92643703811d162"),
|
||||||
|
methods: [
|
||||||
|
("approveAndCall", Method(signature: "approveAndCall(address,uint256,bytes)")),
|
||||||
|
("transfer", Method(signature: "transfer(address,uint256)"))
|
||||||
|
].toTable
|
||||||
|
),
|
||||||
Contract(name: "tribute-to-talk", network: Network.Testnet, address: parseAddress("0xC61aa0287247a0398589a66fCD6146EC0F295432")),
|
Contract(name: "tribute-to-talk", network: Network.Testnet, address: parseAddress("0xC61aa0287247a0398589a66fCD6146EC0F295432")),
|
||||||
Contract(name: "stickers", network: Network.Mainnet, address: parseAddress("0x0577215622f43a39f4bc9640806dfea9b10d2a36"),
|
Contract(name: "stickers", network: Network.Mainnet, address: parseAddress("0x0577215622f43a39f4bc9640806dfea9b10d2a36"),
|
||||||
methods: [
|
methods: [
|
||||||
@ -48,19 +54,35 @@ let CONTRACTS: seq[Contract] = @[
|
|||||||
("getPackData", Method(signature: "getPackData(uint256)", noPadding: true))
|
("getPackData", Method(signature: "getPackData(uint256)", noPadding: true))
|
||||||
].toTable
|
].toTable
|
||||||
),
|
),
|
||||||
Contract(name: "stickers", network: Network.Testnet, address: parseAddress("0x8cc272396be7583c65bee82cd7b743c69a87287d")),
|
Contract(name: "stickers", network: Network.Testnet, address: parseAddress("0x8cc272396be7583c65bee82cd7b743c69a87287d"),
|
||||||
|
methods: [
|
||||||
|
("packCount", Method(signature: "packCount()")),
|
||||||
|
("getPackData", Method(signature: "getPackData(uint256)", noPadding: true))
|
||||||
|
].toTable
|
||||||
|
),
|
||||||
Contract(name: "sticker-market", network: Network.Mainnet, address: parseAddress("0x12824271339304d3a9f7e096e62a2a7e73b4a7e7"),
|
Contract(name: "sticker-market", network: Network.Mainnet, address: parseAddress("0x12824271339304d3a9f7e096e62a2a7e73b4a7e7"),
|
||||||
methods: [
|
methods: [
|
||||||
("buyToken", Method(signature: "buyToken(uint256,address,uint256)"))
|
("buyToken", Method(signature: "buyToken(uint256,address,uint256)"))
|
||||||
].toTable
|
].toTable
|
||||||
),
|
),
|
||||||
Contract(name: "sticker-market", network: Network.Testnet, address: parseAddress("0x6CC7274aF9cE9572d22DFD8545Fb8c9C9Bcb48AD")),
|
Contract(name: "sticker-market", network: Network.Testnet, address: parseAddress("0x6CC7274aF9cE9572d22DFD8545Fb8c9C9Bcb48AD"),
|
||||||
Contract(name: "sticker-pack", network: Network.Mainnet, address: parseAddress("0x110101156e8F0743948B2A61aFcf3994A8Fb172e"),
|
|
||||||
methods: [
|
methods: [
|
||||||
("balanceOf", Method(signature: "balanceOf(address)"))
|
("buyToken", Method(signature: "buyToken(uint256,address,uint256)"))
|
||||||
].toTable
|
].toTable
|
||||||
),
|
),
|
||||||
Contract(name: "sticker-pack", network: Network.Testnet, address: parseAddress("0xf852198d0385c4b871e0b91804ecd47c6ba97351")),
|
Contract(name: "sticker-pack", network: Network.Mainnet, address: parseAddress("0x110101156e8F0743948B2A61aFcf3994A8Fb172e"),
|
||||||
|
methods: [
|
||||||
|
("balanceOf", Method(signature: "balanceOf(address)")),
|
||||||
|
("tokenOfOwnerByIndex", Method(signature: "tokenOfOwnerByIndex(address,uint256)")),
|
||||||
|
("tokenPackId", Method(signature: "tokenPackId(uint256)"))
|
||||||
|
].toTable
|
||||||
|
),
|
||||||
|
Contract(name: "sticker-pack", network: Network.Testnet, address: parseAddress("0xf852198d0385c4b871e0b91804ecd47c6ba97351"),
|
||||||
|
methods: [
|
||||||
|
("balanceOf", Method(signature: "balanceOf(address)")),
|
||||||
|
("tokenOfOwnerByIndex", Method(signature: "tokenOfOwnerByIndex(address,uint256)")),
|
||||||
|
("tokenPackId", Method(signature: "tokenPackId(uint256)"))
|
||||||
|
].toTable),
|
||||||
# Strikers seems dead. Their website doesn't work anymore
|
# Strikers seems dead. Their website doesn't work anymore
|
||||||
Contract(name: "strikers", network: Network.Mainnet, address: parseAddress("0xdcaad9fd9a74144d226dbf94ce6162ca9f09ed7e"),
|
Contract(name: "strikers", network: Network.Mainnet, address: parseAddress("0xdcaad9fd9a74144d226dbf94ce6162ca9f09ed7e"),
|
||||||
methods: [
|
methods: [
|
||||||
@ -85,6 +107,11 @@ proc getContract*(network: Network, name: string): Contract =
|
|||||||
let found = CONTRACTS.filter(contract => contract.name == name and contract.network == network)
|
let found = CONTRACTS.filter(contract => contract.name == name and contract.network == network)
|
||||||
result = if found.len > 0: found[0] else: nil
|
result = if found.len > 0: found[0] else: nil
|
||||||
|
|
||||||
|
func encode*[bits: static[int]](x: Stuint[bits]): EncodeResult =
|
||||||
|
## Encodes a `Stuint` to a textual representation for use in the JsonRPC
|
||||||
|
## `sendTransaction` call.
|
||||||
|
(dynamic: false, data: ('0'.repeat((256 - bits) div 4) & x.dumpHex.map(c => c)).join(""))
|
||||||
|
|
||||||
proc encodeMethod(self: Method): string =
|
proc encodeMethod(self: Method): string =
|
||||||
let hash = $nimcrypto.keccak256.digest(self.signature)
|
let hash = $nimcrypto.keccak256.digest(self.signature)
|
||||||
result = hash[0 .. ^(hash.high - 6)]
|
result = hash[0 .. ^(hash.high - 6)]
|
||||||
@ -98,6 +125,8 @@ proc encodeParam[T](value: T): string =
|
|||||||
result = toHex(value, 64)
|
result = toHex(value, 64)
|
||||||
elif T is EthAddress:
|
elif T is EthAddress:
|
||||||
result = value.toHex()
|
result = value.toHex()
|
||||||
|
elif T is Stuint:
|
||||||
|
result = value.encode().data
|
||||||
else:
|
else:
|
||||||
result = align(value, 64, '0')
|
result = align(value, 64, '0')
|
||||||
|
|
||||||
@ -108,9 +137,6 @@ macro encodeAbi*(self: Method, params: varargs[untyped]): untyped =
|
|||||||
result = quote do:
|
result = quote do:
|
||||||
`result` & encodeParam(`param`)
|
`result` & encodeParam(`param`)
|
||||||
|
|
||||||
proc `$`*(a: EthAddress): string =
|
|
||||||
"0x" & a.toHex()
|
|
||||||
|
|
||||||
proc skip0xPrefix*(s: string): int =
|
proc skip0xPrefix*(s: string): int =
|
||||||
if s.len > 1 and s[0] == '0' and s[1] in {'x', 'X'}: 2
|
if s.len > 1 and s[0] == '0' and s[1] in {'x', 'X'}: 2
|
||||||
else: 0
|
else: 0
|
||||||
|
@ -67,6 +67,8 @@ proc getBalance*(address: EthAddress): int =
|
|||||||
let response = Json.decode(responseStr, RpcResponse)
|
let response = Json.decode(responseStr, RpcResponse)
|
||||||
if response.error != "":
|
if response.error != "":
|
||||||
raise newException(RpcException, "Error getting stickers balance: " & response.error)
|
raise newException(RpcException, "Error getting stickers balance: " & response.error)
|
||||||
|
if response.result == "0x":
|
||||||
|
return 0
|
||||||
result = fromHex[int](response.result)
|
result = fromHex[int](response.result)
|
||||||
|
|
||||||
# Gets number of sticker packs
|
# Gets number of sticker packs
|
||||||
@ -81,6 +83,8 @@ proc getPackCount*(): int =
|
|||||||
let response = Json.decode(responseStr, RpcResponse)
|
let response = Json.decode(responseStr, RpcResponse)
|
||||||
if response.error != "":
|
if response.error != "":
|
||||||
raise newException(RpcException, "Error getting stickers balance: " & response.error)
|
raise newException(RpcException, "Error getting stickers balance: " & response.error)
|
||||||
|
if response.result == "0x":
|
||||||
|
return 0
|
||||||
result = fromHex[int](response.result)
|
result = fromHex[int](response.result)
|
||||||
|
|
||||||
# Gets sticker pack data
|
# Gets sticker pack data
|
||||||
@ -118,17 +122,17 @@ proc getPackData*(id: int): StickerPack =
|
|||||||
# Buys a sticker pack for user
|
# Buys a sticker pack for user
|
||||||
# See https://notes.status.im/Q-sQmQbpTOOWCQcYiXtf5g#Buy-a-Sticker-Pack for more
|
# See https://notes.status.im/Q-sQmQbpTOOWCQcYiXtf5g#Buy-a-Sticker-Pack for more
|
||||||
# details
|
# details
|
||||||
proc buyPack*(packId: int, address: EthAddress, price: int, password: string): string =
|
proc buyPack*(packId: int, address: EthAddress, price: Stuint[256], password: string): string =
|
||||||
let stickerMktContract = contracts.getContract(Network.Mainnet, "sticker-market")
|
let stickerMktContract = contracts.getContract(Network.Mainnet, "sticker-market")
|
||||||
let sntContract = contracts.getContract(Network.Mainnet, "sticker-market")
|
let sntContract = contracts.getContract(Network.Mainnet, "snt")
|
||||||
let buyTxAbiEncoded = stickerMktContract.methods["buyToken"].encodeAbi(packId, address, price)
|
let buyTxAbiEncoded = stickerMktContract.methods["buyToken"].encodeAbi(packId, address, price)
|
||||||
let approveAndCallAbiEncoded = sntContract.methods["approveAndCall"].encodeAbi($stickerMktContract.address, price, buyTxAbiEncoded)
|
let approveAndCallAbiEncoded = sntContract.methods["approveAndCall"].encodeAbi(stickerMktContract.address, price, buyTxAbiEncoded.strip0xPrefix)
|
||||||
let payload = %* [{
|
let payload = %* {
|
||||||
"from": $address,
|
"from": $address,
|
||||||
"to": $sntContract.address,
|
"to": $sntContract.address,
|
||||||
"gas": 200000,
|
# "gas": 200000, # leave out for now
|
||||||
"data": approveAndCallAbiEncoded
|
"data": approveAndCallAbiEncoded
|
||||||
}, "latest"]
|
}
|
||||||
|
|
||||||
let responseStr = status.sendTransaction($payload, password)
|
let responseStr = status.sendTransaction($payload, password)
|
||||||
let response = Json.decode(responseStr, RpcResponse)
|
let response = Json.decode(responseStr, RpcResponse)
|
||||||
@ -136,6 +140,36 @@ proc buyPack*(packId: int, address: EthAddress, price: int, password: string): s
|
|||||||
raise newException(RpcException, "Error getting stickers balance: " & response.error)
|
raise newException(RpcException, "Error getting stickers balance: " & response.error)
|
||||||
result = response.result # should be a tx receipt
|
result = response.result # should be a tx receipt
|
||||||
|
|
||||||
|
proc tokenOfOwnerByIndex*(address: EthAddress, idx: int): int =
|
||||||
|
let contract = contracts.getContract(Network.Testnet, "sticker-pack")
|
||||||
|
let payload = %* [{
|
||||||
|
"to": $contract.address,
|
||||||
|
"data": contract.methods["tokenOfOwnerByIndex"].encodeAbi(address, idx)
|
||||||
|
}, "latest"]
|
||||||
|
|
||||||
|
let responseStr = status.callPrivateRPC("eth_call", payload)
|
||||||
|
let response = Json.decode(responseStr, RpcResponse)
|
||||||
|
if response.error != "":
|
||||||
|
raise newException(RpcException, "Error getting owned tokens: " & response.error)
|
||||||
|
if response.result == "0x":
|
||||||
|
return 0
|
||||||
|
result = fromHex[int](response.result)
|
||||||
|
|
||||||
|
proc getPackIdFromTokenId*(tokenId: int): int =
|
||||||
|
let contract = contracts.getContract(Network.Testnet, "sticker-pack")
|
||||||
|
let payload = %* [{
|
||||||
|
"to": $contract.address,
|
||||||
|
"data": contract.methods["tokenPackId"].encodeAbi(tokenId)
|
||||||
|
}, "latest"]
|
||||||
|
|
||||||
|
let responseStr = status.callPrivateRPC("eth_call", payload)
|
||||||
|
let response = Json.decode(responseStr, RpcResponse)
|
||||||
|
if response.error != "":
|
||||||
|
raise newException(RpcException, "Error getting pack id from token id: " & response.error)
|
||||||
|
if response.result == "0x":
|
||||||
|
return 0
|
||||||
|
result = fromHex[int](response.result)
|
||||||
|
|
||||||
proc saveInstalledStickerPacks*(installedStickerPacks: Table[int, StickerPack]) =
|
proc saveInstalledStickerPacks*(installedStickerPacks: Table[int, StickerPack]) =
|
||||||
let json = %* {}
|
let json = %* {}
|
||||||
for packId, pack in installedStickerPacks.pairs:
|
for packId, pack in installedStickerPacks.pairs:
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import eventemitter, json_serialization, stint, json
|
import eventemitter, json
|
||||||
|
import eth/common/eth_types, stew/byteutils, json_serialization, stint
|
||||||
import accounts/constants
|
import accounts/constants
|
||||||
|
|
||||||
type SignalCallback* = proc(eventMessage: cstring): void {.cdecl.}
|
type SignalCallback* = proc(eventMessage: cstring): void {.cdecl.}
|
||||||
@ -118,6 +119,9 @@ type StickerPack* = object
|
|||||||
proc `%`*(stuint256: Stuint[256]): JsonNode =
|
proc `%`*(stuint256: Stuint[256]): JsonNode =
|
||||||
newJString($stuint256)
|
newJString($stuint256)
|
||||||
|
|
||||||
|
proc `$`*(a: EthAddress): string =
|
||||||
|
"0x" & a.toHex()
|
||||||
|
|
||||||
proc readValue*(reader: var JsonReader, value: var Stuint[256])
|
proc readValue*(reader: var JsonReader, value: var Stuint[256])
|
||||||
{.raises: [IOError, SerializationError, Defect].} =
|
{.raises: [IOError, SerializationError, Defect].} =
|
||||||
try:
|
try:
|
||||||
|
@ -68,6 +68,7 @@ Item {
|
|||||||
style: StickerButton.StyleType.LargeNoIcon
|
style: StickerButton.StyleType.LargeNoIcon
|
||||||
packPrice: price
|
packPrice: price
|
||||||
isInstalled: installed
|
isInstalled: installed
|
||||||
|
isBought: bought
|
||||||
onInstallClicked: root.installClicked(stickers, packId, index)
|
onInstallClicked: root.installClicked(stickers, packId, index)
|
||||||
onUninstallClicked: root.uninstallClicked(packId)
|
onUninstallClicked: root.uninstallClicked(packId)
|
||||||
onCancelClicked: root.cancelClicked(packId)
|
onCancelClicked: root.cancelClicked(packId)
|
||||||
@ -100,6 +101,7 @@ Item {
|
|||||||
packPrice: price
|
packPrice: price
|
||||||
width: 75 // only needed for Qt Creator
|
width: 75 // only needed for Qt Creator
|
||||||
isInstalled: installed
|
isInstalled: installed
|
||||||
|
isBought: bought
|
||||||
onInstallClicked: root.installClicked(stickers, packId, index)
|
onInstallClicked: root.installClicked(stickers, packId, index)
|
||||||
onUninstallClicked: root.uninstallClicked(packId)
|
onUninstallClicked: root.uninstallClicked(packId)
|
||||||
onCancelClicked: root.cancelClicked(packId)
|
onCancelClicked: root.cancelClicked(packId)
|
||||||
|
@ -185,7 +185,7 @@ Popup {
|
|||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: stickerPackListView
|
id: stickerPackListView
|
||||||
property int selectedPackId
|
property int selectedPackId: -1
|
||||||
model: stickerPackList
|
model: stickerPackList
|
||||||
|
|
||||||
delegate: StickerPackIconWithIndicator {
|
delegate: StickerPackIconWithIndicator {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user