From 9ada3bf23c28dca95fec57cd30c7f700f02b3702 Mon Sep 17 00:00:00 2001 From: Sale Djenic Date: Tue, 1 Feb 2022 10:37:32 +0100 Subject: [PATCH] refactor: add new module for stickers (#107) --- status/statusgo_backend_new/core.nim | 12 +- status/statusgo_backend_new/ens.nim | 123 ++++++++----------- status/statusgo_backend_new/eth.nim | 14 ++- status/statusgo_backend_new/stickers.nim | 43 +++++++ status/statusgo_backend_new/transactions.nim | 5 +- 5 files changed, 122 insertions(+), 75 deletions(-) create mode 100644 status/statusgo_backend_new/stickers.nim diff --git a/status/statusgo_backend_new/core.nim b/status/statusgo_backend_new/core.nim index 24be408..5f75254 100644 --- a/status/statusgo_backend_new/core.nim +++ b/status/statusgo_backend_new/core.nim @@ -1,4 +1,4 @@ -import json, json_serialization, strformat, chronicles +import json, json_serialization, strformat, chronicles, nimcrypto import status_go import response_type @@ -42,3 +42,13 @@ proc signMessage*(rpcParams: string): string = proc signTypedData*(data: string, address: string, password: string): string = return $status_go.signTypedData(data, address, password) + +proc sendTransaction*(inputJSON: string, password: string): RpcResponse[JsonNode] + {.raises: [RpcException, ValueError, Defect, SerializationError].} = + try: + var hashed_password = "0x" & $keccak_256.digest(password) + let rpcResponseRaw = status_go.sendTransaction(inputJSON, hashed_password) + result = Json.decode(rpcResponseRaw, RpcResponse[JsonNode]) + except RpcException as e: + error "error sending tx", inputJSON, exception=e.msg + raise newException(RpcException, e.msg) \ No newline at end of file diff --git a/status/statusgo_backend_new/ens.nim b/status/statusgo_backend_new/ens.nim index ed31e50..ee220af 100644 --- a/status/statusgo_backend_new/ens.nim +++ b/status/statusgo_backend_new/ens.nim @@ -1,80 +1,59 @@ -import json, web3/[conversions, ethtypes] -import ./core, ./response_type -import ../types/transaction -import ./conversions as conv -import ./utils -export response_type +import sequtils +import strformat +import strutils +import nimcrypto +import json +import json_serialization +import tables +import stew/byteutils +import unicode +import algorithm +import web3/[ethtypes, conversions], stew/byteutils, stint +import chronicles, libp2p/[multihash, multicodec, cid] +import ./eth -proc resolver*(chainId: int, username: string): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, username] +proc namehash*(ensName:string): string = + let name = ensName.toLower() + var node:array[32, byte] - return core.callPrivateRPC("ens_resolver", payload) + node.fill(0) + var parts = name.split(".") + for i in countdown(parts.len - 1,0): + let elem = keccak_256.digest(parts[i]).data + var concatArrays: array[64, byte] + concatArrays[0..31] = node + concatArrays[32..63] = elem + node = keccak_256.digest(concatArrays).data -proc ownerOf*(chainId: int, username: string): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, username] + result = "0x" & node.toHex() - return core.callPrivateRPC("ens_ownerOf", payload) +const registry* = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" +const resolver_signature = "0x0178b8bf" +proc resolver*(usernameHash: string): string = + let payload = %* [{ + "to": registry, + "from": "0x0000000000000000000000000000000000000000", + "data": fmt"{resolver_signature}{userNameHash}" + }, "latest"] -proc contentHash*(chainId: int, username: string): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, username] + var resolverAddr = eth.doEthCall(payload).result.getStr() + resolverAddr.removePrefix("0x000000000000000000000000") + result = "0x" & resolverAddr - return core.callPrivateRPC("ens_contentHash", payload) +const contenthash_signature = "0xbc1c58d1" # contenthash(bytes32) +proc contenthash*(ensAddr: string): string = + var ensHash = namehash(ensAddr) + ensHash.removePrefix("0x") + let ensResolver = resolver(ensHash) + let payload = %* [{ + "to": ensResolver, + "from": "0x0000000000000000000000000000000000000000", + "data": fmt"{contenthash_signature}{ensHash}" + }, "latest"] -proc publicKeyOf*(chainId: int, username: string): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, username] + let bytesResponse = eth.doEthCall(payload).result.getStr() + if bytesResponse == "0x": + return "" - return core.callPrivateRPC("ens_publicKeyOf", payload) - -proc addressOf*(chainId: int, username: string): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, username] - - return core.callPrivateRPC("ens_addressOf", payload) - -proc expireAt*(chainId: int, username: string): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, username] - - return core.callPrivateRPC("ens_expireAt", payload) - -proc price*(chainId: int): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId] - return core.callPrivateRPC("ens_price", payload) - -proc resourceURL*(chainId: int, username: string): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, username] - return core.callPrivateRPC("ens_resourceURL", payload) - -proc register*( - chainId: int, txData: TransactionData, password: string, username: string, pubkey: string -): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, txData, hashPassword(password), username, pubkey] - return core.callPrivateRPC("ens_register", payload) - -proc registerEstimate*( - chainId: int, txData: TransactionData, username: string, pubkey: string -): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, txData, username, pubkey] - return core.callPrivateRPC("ens_registerEstimate", payload) - -proc release*( - chainId: int, txData: TransactionData, password: string, username: string -): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, txData, hashPassword(password), username] - return core.callPrivateRPC("ens_release", payload) - -proc releaseEstimate*( - chainId: int, txData: TransactionData, username: string -): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, txData, username] - return core.callPrivateRPC("ens_releaseEstimate", payload) - -proc setPubKey*( - chainId: int, txData: TransactionData, password: string, username: string, pubkey: string -): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, txData, hashPassword(password), username, pubkey] - return core.callPrivateRPC("ens_setPubKey", payload) - -proc setPubKeyEstimate*( - chainId: int, txData: TransactionData, username: string, pubkey: string -): RpcResponse[JsonNode] {.raises: [Exception].} = - let payload = %* [chainId, txData, username, pubkey] - return core.callPrivateRPC("ens_setPubKeyEstimate", payload) \ No newline at end of file + let size = fromHex(Stuint[256], bytesResponse[66..129]).truncate(int) + result = bytesResponse[130..129+size*2] \ No newline at end of file diff --git a/status/statusgo_backend_new/eth.nim b/status/statusgo_backend_new/eth.nim index 87852c3..c7af8d2 100644 --- a/status/statusgo_backend_new/eth.nim +++ b/status/statusgo_backend_new/eth.nim @@ -14,5 +14,17 @@ proc getEthBalance*(address: string): RpcResponse[JsonNode] {.raises: [Exception let payload = %* [address, "latest"] return core.callPrivateRPC("eth_getBalance", payload) -proc call*(payload = %* []): RpcResponse[JsonNode] {.raises: [Exception].} = +proc getTokenBalance*(tokenAddress: string, accountAddress: string): RpcResponse[JsonNode] {.raises: [Exception].} = + var postfixedAccount: string = accountAddress + postfixedAccount.removePrefix("0x") + let payload = %* [{ + "to": tokenAddress, "from": accountAddress, "data": fmt"0x70a08231000000000000000000000000{postfixedAccount}" + }, "latest"] return core.callPrivateRPC("eth_call", payload) + +proc sendTransaction*(transactionData: string, password: string): RpcResponse[JsonNode] {.raises: [Exception].} = + core.sendTransaction(transactionData, password) + +# This is the replacement of the `call` function +proc doEthCall*(payload = %* []): RpcResponse[JsonNode] {.raises: [Exception].} = + core.callPrivateRPC("eth_call", payload) \ No newline at end of file diff --git a/status/statusgo_backend_new/stickers.nim b/status/statusgo_backend_new/stickers.nim new file mode 100644 index 0000000..1e3a28a --- /dev/null +++ b/status/statusgo_backend_new/stickers.nim @@ -0,0 +1,43 @@ +import json +import ../statusgo_backend_new/eth as eth + + +# Retrieves number of sticker packs owned by user +# See https://notes.status.im/Q-sQmQbpTOOWCQcYiXtf5g#Read-Sticker-Packs-owned-by-a-user +# for more details +proc getBalance*(address: string, data: string): RpcResponse[JsonNode] {.raises: [Exception].} = + let payload = %* [{ + "to": address, + "data": data + }, "latest"] + + let response = eth.doEthCall(payload) + + if not response.error.isNil: + raise newException(RpcException, "Error getting stickers balance: " & response.error.message) + + return response + +proc tokenOfOwnerByIndex*(address: string, data: string): RpcResponse[JsonNode] {.raises: [Exception].} = + let payload = %* [{ + "to": address, + "data": data + }, "latest"] + + let response = eth.doEthCall(payload) + if not response.error.isNil: + raise newException(RpcException, "Error getting owned tokens: " & response.error.message) + + return response + +proc getPackIdFromTokenId*(address: string, data: string): RpcResponse[JsonNode] {.raises: [Exception].} = + let payload = %* [{ + "to": address, + "data": data + }, "latest"] + + let response = eth.doEthCall(payload) + if not response.error.isNil: + raise newException(RpcException, "Error getting pack id from token id: " & response.error.message) + + return response diff --git a/status/statusgo_backend_new/transactions.nim b/status/statusgo_backend_new/transactions.nim index db3f241..e91ed62 100644 --- a/status/statusgo_backend_new/transactions.nim +++ b/status/statusgo_backend_new/transactions.nim @@ -14,4 +14,7 @@ proc getTransfersByAddress*(address: string, toBlock: Uint256, limit: int, loadM limitParsed = "0x" & limit.toHex.stripLeadingZeros callPrivateRPC("wallet_getTransfersByAddress", %* [address, toBlockParsed, limitParsed, loadMore]) - \ No newline at end of file + +proc trackPendingTransaction*(hash: string, fromAddress: string, toAddress: string, trxType: PendingTransactionType, data: string): RpcResponse[JsonNode] {.raises: [Exception].} = + let payload = %* [{"hash": hash, "from": fromAddress, "to": toAddress, "type": $trxType, "additionalData": data, "data": "", "value": 0, "timestamp": 0, "gasPrice": 0, "gasLimit": 0}] + callPrivateRPC("wallet_storePendingTransaction", payload) \ No newline at end of file