Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8febe65
(feat) Test using Prcryptodome to remove pysha3
Jun 1, 2023
ae8c316
(feat) Test using Prcryptodome to remove pysha3
Jun 1, 2023
111f8bc
(fix) Removed eip712-struct from the project because it depends on py…
Jun 5, 2023
aedc9c8
(fix) Refactor dependencies to remove the pysha3 library requirement
Jun 5, 2023
e0f2fe4
Merge branch 'fix/remove_pysha3_dependency' of https://github.com/Inj…
Jun 5, 2023
8eddc54
(fix) Change setup.py version to enable the release of this version
Jun 5, 2023
c89af2a
(fix) Added restriction in setup.py to require Python >= 3.9 (the new…
Jun 5, 2023
5f4a42f
(fix) Added logic in Composer class to parse the transaction response…
Jun 9, 2023
81ca1ef
(fix) Updating README and the version number to prepare the PR to be …
Jun 9, 2023
7b85dbb
Merge pull request #212 from InjectiveLabs/fix/adapt_code_to_transact…
achilleas-kal Jun 12, 2023
1fe5fb8
Merge branch 'master' of https://github.com/InjectiveLabs/sdk-python …
Jun 12, 2023
39b618a
(fix) Change version numbers to 0.6.4 in setup.py and README file in …
Jun 13, 2023
df9bafe
Merge pull request #213 from InjectiveLabs/release/staging_v064
aarmoa Jun 15, 2023
51a9a33
(fix) Fix instanciation of mainnet network instance to not support `k…
Jun 15, 2023
9af635e
(fix) Change version number and changelog
Jun 15, 2023
2940568
Merge pull request #214 from InjectiveLabs/fix/remove_k8s_as_valid_ma…
aarmoa Jun 15, 2023
26554d9
Merge pull request #215 from InjectiveLabs/fix/sync_dev_with_master_065
aarmoa Jun 15, 2023
cb09390
(feat) Test using Prcryptodome to remove pysha3
Jun 1, 2023
900ba8c
(fix) Removed eip712-struct from the project because it depends on py…
Jun 5, 2023
ed335ba
(fix) Refactor dependencies to remove the pysha3 library requirement
Jun 5, 2023
0829eea
(feat) Test using Prcryptodome to remove pysha3
Jun 1, 2023
a6c45af
(fix) Change setup.py version to enable the release of this version
Jun 5, 2023
c2de4bb
(fix) Added restriction in setup.py to require Python >= 3.9 (the new…
Jun 5, 2023
7ddb66d
(fix) Added missing required library in setup.py
Jun 15, 2023
72b2f8a
Merge branch 'fix/remove_pysha3_dependency' of https://github.com/Inj…
Jun 15, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,28 @@ verify_ssl = true
name = "pypi"

[packages]
protobuf = "*"
grpcio-tools = "*"
grpcio = "*"
asyncio = "*"
aiocron = "*"
aiohttp = "*"
ecdsa = "*"
asyncio = "*"
bech32 = "*"
mnemonic = "*"
hdwallets = "*"
bip32 = "*"
requests = "*"
eip712_structs = "*"
coincurve = "*"
aiocron = "*"
websockets = "*"
ecdsa = "*"
eip712 = "*"
grpcio = "*"
grpcio-tools = "*"
hdwallets = "*"
mnemonic = "*"
protobuf = "*"
requests = "*"
safe-pysha3 = "*"
urllib3 = "<2"
websockets = "*"

[dev-packages]
pytest = "*"
pytest-asyncio = "*"
requests-mock = "*"

[requires]
python_version = "3.9"
python_version = "3"
547 changes: 475 additions & 72 deletions Pipfile.lock

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,20 @@ make tests
```

### Changelogs
**0.6.4**(change before release)
**0.7**
* Removed references to pysha3 library (and also eip712-struct that required it) and replaced it with other implementation to allow the project to work with Python 3.11

**0.6.5**
* Removed `k8s` from the list of supported mainnet nodes (`lb` should be used instead)

**0.6.4**
* Change logging logic to use different loggers for each module and class
* Solved issue preventing requesting spot and derivative historical orders for more than one market_id
* Add `pytest` as a development dependency to implement and run unit tests

**0.6.3.3**
* Update the code to the new structure of transaction responses

**0.6.3.1**
* Update the code to the new structure of transaction simulation responses

Expand Down
11 changes: 9 additions & 2 deletions examples/exchange_client/explorer_rpc/1_GetTxByHash.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@
import logging

from pyinjective.async_client import AsyncClient
from pyinjective.composer import Composer
from pyinjective.constant import Network

async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network, insecure=False)
composer = Composer(network=network.string())
tx_hash = "0F3EBEC1882E1EEAC5B7BDD836E976250F1CD072B79485877CEACCB92ACDDF52"
account = await client.get_tx_by_hash(tx_hash=tx_hash)
print(account)
transaction_response = await client.get_tx_by_hash(tx_hash=tx_hash)
print(transaction_response)

transaction_messages = composer.UnpackTransactionMessages(transaction=transaction_response.data)
print(transaction_messages)
first_message = transaction_messages[0]
print(first_message)

if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
12 changes: 9 additions & 3 deletions examples/exchange_client/explorer_rpc/2_AccountTxs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@
import logging

from pyinjective.async_client import AsyncClient
from pyinjective.composer import Composer
from pyinjective.constant import Network

async def main() -> None:
# select network: local, testnet, mainnet
network = Network.testnet()
client = AsyncClient(network, insecure=False)
composer = Composer(network=network.string())
address = "inj1phd706jqzd9wznkk5hgsfkrc8jqxv0kmlj0kex"
type = "cosmos.bank.v1beta1.MsgSend"
message_type = "cosmos.bank.v1beta1.MsgSend"
limit = 2
account = await client.get_account_txs(address=address, type=type, limit=limit)
print(account)
transactions_response = await client.get_account_txs(address=address, type=message_type, limit=limit)
print(transactions_response)
first_transaction_messages = composer.UnpackTransactionMessages(transaction=transactions_response.data[0])
print(first_transaction_messages)
first_message = first_transaction_messages[0]
print(first_message)

if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
45 changes: 43 additions & 2 deletions pyinjective/composer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import json
import logging

from google.protobuf import any_pb2, message, timestamp_pb2
from google.protobuf import any_pb2, timestamp_pb2, json_format

from .proto.cosmos.authz.v1beta1 import authz_pb2 as cosmos_authz_pb
from .proto.cosmos.authz.v1beta1 import tx_pb2 as cosmos_authz_tx_pb
Expand All @@ -13,7 +13,6 @@

from .proto.injective.exchange.v1beta1 import tx_pb2 as injective_exchange_tx_pb
from pyinjective.proto.injective.exchange.v1beta1 import exchange_pb2 as injective_dot_exchange_dot_v1beta1_dot_exchange__pb2
from .proto.injective.types.v1beta1 import tx_response_pb2 as tx_response_pb

from .proto.injective.auction.v1beta1 import tx_pb2 as injective_auction_tx_pb

Expand Down Expand Up @@ -958,3 +957,45 @@ def UnpackMsgExecResponse(msg_type, data):

responses = [header_map[msg_type].FromString(result) for result in data.results]
return responses

@staticmethod
def UnpackTransactionMessages(transaction):
meta_messages = json.loads(transaction.messages.decode())

header_map = {
"/injective.exchange.v1beta1.MsgCreateSpotLimitOrder": injective_exchange_tx_pb.MsgCreateSpotLimitOrderResponse,
"/injective.exchange.v1beta1.MsgCreateSpotMarketOrder": injective_exchange_tx_pb.MsgCreateSpotMarketOrderResponse,
"/injective.exchange.v1beta1.MsgCreateDerivativeLimitOrder": injective_exchange_tx_pb.MsgCreateDerivativeLimitOrderResponse,
"/injective.exchange.v1beta1.MsgCreateDerivativeMarketOrder": injective_exchange_tx_pb.MsgCreateDerivativeMarketOrderResponse,
"/injective.exchange.v1beta1.MsgCancelSpotOrder": injective_exchange_tx_pb.MsgCancelSpotOrderResponse,
"/injective.exchange.v1beta1.MsgCancelDerivativeOrder": injective_exchange_tx_pb.MsgCancelDerivativeOrderResponse,
"/injective.exchange.v1beta1.MsgBatchCancelSpotOrders": injective_exchange_tx_pb.MsgBatchCancelSpotOrdersResponse,
"/injective.exchange.v1beta1.MsgBatchCancelDerivativeOrders": injective_exchange_tx_pb.MsgBatchCancelDerivativeOrdersResponse,
"/injective.exchange.v1beta1.MsgBatchCreateSpotLimitOrders": injective_exchange_tx_pb.MsgBatchCreateSpotLimitOrders,
"/injective.exchange.v1beta1.MsgBatchCreateDerivativeLimitOrders": injective_exchange_tx_pb.MsgBatchCreateDerivativeLimitOrders,
"/injective.exchange.v1beta1.MsgBatchUpdateOrders": injective_exchange_tx_pb.MsgBatchUpdateOrders,
"/injective.exchange.v1beta1.MsgDeposit": injective_exchange_tx_pb.MsgDeposit,
"/injective.exchange.v1beta1.MsgWithdraw": injective_exchange_tx_pb.MsgWithdraw,
"/injective.exchange.v1beta1.MsgSubaccountTransfer": injective_exchange_tx_pb.MsgSubaccountTransfer,
"/injective.exchange.v1beta1.MsgLiquidatePosition": injective_exchange_tx_pb.MsgLiquidatePosition,
"/injective.exchange.v1beta1.MsgIncreasePositionMargin": injective_exchange_tx_pb.MsgIncreasePositionMargin,
"/injective.auction.v1beta1.MsgBid": injective_auction_tx_pb.MsgBid,
"/injective.exchange.v1beta1.MsgCreateBinaryOptionsLimitOrder": injective_exchange_tx_pb.MsgCreateBinaryOptionsLimitOrder,
"/injective.exchange.v1beta1.MsgCreateBinaryOptionsMarketOrder": injective_exchange_tx_pb.MsgCreateBinaryOptionsMarketOrder,
"/injective.exchange.v1beta1.MsgCancelBinaryOptionsOrder": injective_exchange_tx_pb.MsgCancelBinaryOptionsOrder,
"/injective.exchange.v1beta1.MsgAdminUpdateBinaryOptionsMarket": injective_exchange_tx_pb.MsgAdminUpdateBinaryOptionsMarket,
"/injective.exchange.v1beta1.MsgInstantBinaryOptionsMarketLaunch": injective_exchange_tx_pb.MsgInstantBinaryOptionsMarketLaunch,
"/cosmos.bank.v1beta1.MsgSend": cosmos_bank_tx_pb.MsgSend,
"/cosmos.authz.v1beta1.MsgGrant": cosmos_authz_tx_pb.MsgGrant,
"/cosmos.authz.v1beta1.MsgExec": cosmos_authz_tx_pb.MsgExec,
"/cosmos.authz.v1beta1.MsgRevoke": cosmos_authz_tx_pb.MsgRevoke,
"/injective.oracle.v1beta1.MsgRelayPriceFeedPrice": injective_oracle_tx_pb.MsgRelayPriceFeedPrice,
"/injective.oracle.v1beta1.MsgRelayProviderPrices": injective_oracle_tx_pb.MsgRelayProviderPrices,
}

msgs = []
for msg in meta_messages:
msg_as_string_dict = json.dumps(msg["value"])
msgs.append(json_format.Parse(msg_as_string_dict, header_map[msg["type"]]()))

return msgs
1 change: 0 additions & 1 deletion pyinjective/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ def testnet(cls):
@classmethod
def mainnet(cls, node='lb'):
nodes = [
'k8s', # us, prod
'lb', # us, asia, prod
'sentry0', # ca, prod
'sentry1', # ca, prod
Expand Down
84 changes: 46 additions & 38 deletions pyinjective/orderhash.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,48 @@
import sha3
import requests
from decimal import Decimal
from eip712_structs import make_domain, EIP712Struct, String

class OrderInfo(EIP712Struct):
SubaccountId = String()
FeeRecipient = String()
Price = String()
Quantity = String()

class SpotOrder(EIP712Struct):
MarketId = String()
OrderInfo = OrderInfo
Salt = String()
OrderType = String()
TriggerPrice = String()

class DerivativeOrder(EIP712Struct):
MarketId = String()
OrderInfo = OrderInfo
OrderType = String()
Margin = String()
TriggerPrice = String()
Salt = String()

EIP712_domain = make_domain(
name='Injective Protocol',
version='2.0.0',
chainId=888,
verifyingContract='0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
salt='0x0000000000000000000000000000000000000000000000000000000000000000'
)

domain_separator = EIP712_domain.hash_struct()

from eip712.messages import EIP712Message, EIP712Type
from eth_account.messages import _hash_eip191_message as hash_eip191_message
from hexbytes import HexBytes


class OrderInfo(EIP712Type):
SubaccountId: "string"
FeeRecipient: "string"
Price: "string"
Quantity: "string"


class SpotOrder(EIP712Message):
_name_ = "Injective Protocol"
_version_ = "2.0.0"
_chainId_ = 888
_verifyingContract_ = "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
_salt_ = HexBytes("0x0000000000000000000000000000000000000000000000000000000000000000")

MarketId: "string"
OrderInfo: OrderInfo
Salt: "string"
OrderType: "string"
TriggerPrice: "string"


class DerivativeOrder(EIP712Message):
_name_ = "Injective Protocol"
_version_ = "2.0.0"
_chainId_ = 888
_verifyingContract_ = "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
_salt_ = HexBytes("0x0000000000000000000000000000000000000000000000000000000000000000")

MarketId: "string"
OrderInfo: OrderInfo
OrderType: "string"
Margin: "string"
TriggerPrice: "string"
Salt: "string"


# domain_separator = EIP712_domain.hash_struct()
order_type_dict = {0: '\x00', 1: '\x01', 2: '\x02', 3: '\x03', 4: '\x04', 5: '\x05', 6: '\x06', 7: '\x07', 8: '\x08'}

class OrderHashResponse:
Expand Down Expand Up @@ -127,8 +137,6 @@ def build_eip712_msg(order, nonce):
)

def hash_order(msg):
typed_data_hash = msg.hash_struct()
typed_bytes = b'\x19\x01' + domain_separator + typed_data_hash
keccak256 = sha3.keccak_256()
keccak256.update(typed_bytes)
return '0x' + keccak256.hexdigest()
signable_message = msg.signable_message
hex_digest = hash_eip191_message(signable_message=signable_message).hex()
return "0x" + hex_digest
2 changes: 1 addition & 1 deletion pyinjective/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def with_messages(self, *msgs: message.Message) -> "Transaction":

def with_sender(self, client: Client, sender: str) -> "Transaction":
if len(self.msgs) == 0:
raise EmptyMsgError("messsage is empty, please use with_messages at least 1 message")
raise EmptyMsgError("message is empty, please use with_messages at least 1 message")
account = client.get_account(sender)
if account:
self.account_num = account.account_number
Expand Down
18 changes: 6 additions & 12 deletions pyinjective/wallet.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import sys
import sha3
import hashlib
import bech32
import aiohttp
import json
import requests
from typing import Tuple

from bech32 import bech32_encode, bech32_decode, convertbits
from bip32 import BIP32
from ecdsa import SigningKey, VerifyingKey, SECP256k1, BadSignatureError
Expand All @@ -25,6 +24,7 @@

DEFAULT_DERIVATION_PATH = "m/44'/60'/0'/0/0"


class PrivateKey:
"""
Class for wrapping SigningKey that is used for signature creation and public key derivation.
Expand Down Expand Up @@ -99,9 +99,8 @@ def sign(self, msg: bytes) -> bytes:

:return: a signature of this private key over the given message
"""
# return self.signing_key.sign_deterministic(msg, hashfunc=hashlib.sha256, sigencode=sigencode_string_canonize)
return self.signing_key.sign_deterministic(msg, hashfunc=sha3.keccak_256, sigencode=sigencode_string_canonize)

return self.signing_key.sign_deterministic(msg, hashfunc=sha3.keccak_256, sigencode=sigencode_string_canonize)

class PublicKey:
"""
Expand Down Expand Up @@ -174,15 +173,10 @@ def to_cons_bech32(self) -> str:

def to_address(self) -> "Address":
"""Return address instance from this public key"""
# pubkey = self.verify_key.to_string("compressed")
# s = hashlib.new("sha256", pubkey).digest()
# r = hashlib.new("ripemd160", s).digest()
# return Address(r)

pubkey = self.verify_key.to_string("uncompressed")
k = sha3.keccak_256()
k.update(pubkey[1:])
addr = k.digest()[12:]
keccak_hash = sha3.keccak_256()
keccak_hash.update(pubkey[1:])
addr = keccak_hash.digest()[12:]
return Address(addr)

def verify(self, msg: bytes, sig: bytes) -> bool:
Expand Down
29 changes: 16 additions & 13 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,33 @@
URL = "https://github.com/InjectiveLabs/sdk-python"
EMAIL = "achilleas@injectivelabs.com"
AUTHOR = "Injective Labs"
REQUIRES_PYTHON = ">=3.7, <3.11"
VERSION = "0.6.4-pre"
REQUIRES_PYTHON = ">=3.9"
VERSION = "0.7"

REQUIRED = [
"protobuf",
"grpcio-tools",
"grpcio",
"asyncio",
"aiohttp",
"ecdsa",
"aiocron",
"asyncio",
"bech32",
"mnemonic",
"hdwallets",
"bip32",
"requests",
"eip712_structs",
"coincurve",
"aiocron",
"websockets"
"ecdsa",
"eip712",
"grpcio",
"grpcio-tools",
"hdwallets",
"mnemonic",
"protobuf",
"requests",
"safe-pysha3",
"urllib3",
"websockets",
]

DEV_REQUIRED = [
"pytest",
"pytest-asyncio",
"request-mock",
]

# The rest you shouldn't have to touch too much :)
Expand Down
Loading