convex-sdk 0.3.2__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. convex_sdk/__init__.py +12 -0
  2. convex_sdk/account.py +192 -0
  3. convex_sdk/contract.py +211 -0
  4. convex_sdk/convex.py +813 -0
  5. convex_sdk/exceptions.py +23 -0
  6. convex_sdk/key_pair.py +570 -0
  7. convex_sdk/models.py +86 -0
  8. convex_sdk/py.typed +0 -0
  9. convex_sdk/registry.py +85 -0
  10. convex_sdk/tool/__init__.py +0 -0
  11. convex_sdk/tool/command/__init__.py +0 -0
  12. convex_sdk/tool/command/account_balance_command.py +60 -0
  13. convex_sdk/tool/command/account_command.py +68 -0
  14. convex_sdk/tool/command/account_create_command.py +92 -0
  15. convex_sdk/tool/command/account_fund_command.py +68 -0
  16. convex_sdk/tool/command/account_info_command.py +59 -0
  17. convex_sdk/tool/command/account_name_register_command.py +81 -0
  18. convex_sdk/tool/command/account_name_resolve_command.py +56 -0
  19. convex_sdk/tool/command/account_topup_command.py +60 -0
  20. convex_sdk/tool/command/argparse_typing.py +35 -0
  21. convex_sdk/tool/command/command_base.py +136 -0
  22. convex_sdk/tool/command/help_command.py +29 -0
  23. convex_sdk/tool/command/peer_command.py +55 -0
  24. convex_sdk/tool/command/peer_create_command.py +105 -0
  25. convex_sdk/tool/command/query_command.py +66 -0
  26. convex_sdk/tool/command/submit_command.py +65 -0
  27. convex_sdk/tool/convex_tool.py +110 -0
  28. convex_sdk/tool/output.py +68 -0
  29. convex_sdk-0.3.2.data/scripts/convex_tools.py +13 -0
  30. convex_sdk-0.3.2.dist-info/METADATA +272 -0
  31. convex_sdk-0.3.2.dist-info/RECORD +34 -0
  32. convex_sdk-0.3.2.dist-info/WHEEL +6 -0
  33. convex_sdk-0.3.2.dist-info/licenses/LICENSE +201 -0
  34. convex_sdk-0.3.2.dist-info/top_level.txt +1 -0
convex_sdk/__init__.py ADDED
@@ -0,0 +1,12 @@
1
+ """
2
+
3
+ Convex API Python Library
4
+
5
+ """
6
+
7
+ from convex_sdk.account import Account # type: ignore # noqa: F401
8
+ from convex_sdk.convex import Convex # type: ignore # noqa: F401
9
+ from convex_sdk.contract import Contract # type: ignore # noqa: F401
10
+ from convex_sdk.key_pair import KeyPair # type: ignore # noqa: F401
11
+
12
+ __version__ = '0.3.2'
convex_sdk/account.py ADDED
@@ -0,0 +1,192 @@
1
+ """
2
+
3
+ Account class for convex api
4
+
5
+
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import re
10
+ from convex_sdk.key_pair import KeyPair
11
+
12
+
13
+ class Account:
14
+
15
+ @staticmethod
16
+ def is_address(text: int | str) -> bool:
17
+ """
18
+ Returns True if the text value is a valid address.
19
+
20
+ :param str, int text: Possible address field.
21
+
22
+ :returns: True if the text field is a valid address.
23
+
24
+ """
25
+ return Account.to_address(text) >= 0
26
+
27
+ @staticmethod
28
+ def to_address(value: Account | int | str) -> int:
29
+ """
30
+ Convert address text with possible leading '#' to an integer address value.
31
+
32
+ :param str text: Address text to convert
33
+
34
+ :returns: Integer address
35
+
36
+ :raises ValueError: If the address is not valid
37
+
38
+ """
39
+ if isinstance(value, Account):
40
+ return value.address
41
+ elif isinstance(value, int):
42
+ return int(value)
43
+ else:
44
+ try:
45
+ address = int(re.sub(r'^#', '', value.strip()))
46
+ except ValueError:
47
+ raise ValueError(f'Invalid address {value}')
48
+ return address
49
+
50
+ def __init__(self, key_pair: KeyPair, address: Account | int | str, name: str | None = None):
51
+ """
52
+
53
+ Create a new account with a private key KeyPair.
54
+
55
+ :param KeyPair key_pair: The public/private key of the account
56
+
57
+ :param int address: address of the account
58
+
59
+ :param str name: Optional name of the account
60
+
61
+ .. code-block:: python
62
+
63
+ >>> # import convex-api
64
+ >>> from convex_sdk import Convex, KeyPair, Account
65
+
66
+ >>> # setup the network connection
67
+ >>> convex = Convex('https://convex.world')
68
+
69
+ >>> # create a random keypair
70
+ >>> key_pair = KeyPair()
71
+
72
+ >>> # create a new account and address
73
+ >>> account = convex.create_account(key_pair)
74
+
75
+ >>> # export the private key to a file
76
+ >>> key_pair.export_to_file('/tmp/my_account.pem', 'my secret password')
77
+
78
+ >>> # save the address for later
79
+ >>> my_address = account.address
80
+
81
+ >>> # ----
82
+
83
+ >>> # now import the account and address for later use
84
+ >>> key_pair = KeyPair.import_from_file('/tmp/my_account.pem', 'my secret password')
85
+ >>> account = Account(key_pair, my_address)
86
+
87
+
88
+ """
89
+ self._key_pair = key_pair
90
+ self._address = Account.to_address(address)
91
+ self._name = name
92
+
93
+ def sign(self, hash_text: str) -> str:
94
+ """
95
+
96
+ Sign a hash text using the internal key_pair.
97
+
98
+ :param str hash_text: Hex string of the hash to sign
99
+
100
+ :returns: Hex string of the signed text
101
+
102
+ .. code-block:: python
103
+
104
+ >>> # create an account
105
+ >>> account = convex.create_account(key_pair)
106
+ >>> # sign a given hash
107
+ >>> sig = account.sign('7e2f1062f5fc51ed65a28b5945b49425aa42df6b7e67107efec357794096e05e')
108
+ >>> print(sig)
109
+ '5d41b964c63d1087ad66e58f4f9d3fe2b7bd0560b..'
110
+
111
+ """
112
+ return self._key_pair.sign(hash_text)
113
+
114
+ def __str__(self):
115
+ return f'Account {self.address}:{self.key_pair.public_key}'
116
+
117
+ @property
118
+ def address(self) -> int:
119
+ """
120
+
121
+ :returns: the network account address
122
+ :rtype: int
123
+
124
+ .. code-block:: python
125
+
126
+ >>> # create an account with the network
127
+ >>> key_pair = KeyPair()
128
+ >>> account = convex.create_account(key_pair)
129
+ >>> print(account.address)
130
+ 42
131
+
132
+ """
133
+ return self._address
134
+
135
+ @address.setter
136
+ def address(self, value: Account | int | str) -> None:
137
+ """
138
+
139
+ Sets the network address of this account
140
+
141
+ :param value: Address to use for this account
142
+ :type value: str, int
143
+
144
+ .. code-block:: python
145
+
146
+ >>> # import the account keys
147
+ >>> key_pair = KeyPair.import_from_mnemonic('my private key words ..')
148
+
149
+ >>> account = convex.create_account(key_pair)
150
+ >>> # set the address that was given to us when we created the account on the network
151
+ >>> account.address = 42
152
+
153
+ """
154
+ self._address = Account.to_address(value)
155
+
156
+ @property
157
+ def name(self) -> str | None:
158
+ return self._name
159
+
160
+ @name.setter
161
+ def name(self, value: str) -> None:
162
+ self._name = value
163
+
164
+ @property
165
+ def public_key(self) -> bytes:
166
+ """
167
+
168
+ Return the public key of the account in the format '0x....'
169
+
170
+ :returns: public_key with leading '0x'
171
+ :rtype: str
172
+
173
+ .. code-block:: python
174
+
175
+ >>> # create an account with the network
176
+ >>> account = convex.create_account(key_pair)
177
+
178
+ >>> # show the public key as a hex string
179
+ >>> print(account.public_key)
180
+ 0x36d8c5c40dbe2d1b0131acf41c38b9d37ebe04d85...
181
+
182
+ """
183
+ return self._key_pair.public_key_bytes
184
+
185
+ @property
186
+ def key_pair(self) -> KeyPair:
187
+ """
188
+
189
+ Return the internal KeyPair object for this account
190
+
191
+ """
192
+ return self._key_pair
convex_sdk/contract.py ADDED
@@ -0,0 +1,211 @@
1
+ """
2
+
3
+
4
+ Convex Contract
5
+
6
+ """
7
+ from __future__ import annotations
8
+
9
+ from typing import TYPE_CHECKING
10
+
11
+ if TYPE_CHECKING:
12
+ from convex_sdk.convex import Convex
13
+
14
+ import re
15
+
16
+ from convex_sdk.account import Account
17
+
18
+
19
+ class Contract:
20
+ def __init__(self, convex: Convex):
21
+ """
22
+
23
+ Contract class to provide access and name resolution to deployed convex contracts.
24
+
25
+ """
26
+ self._convex = convex
27
+ self._name = None
28
+ self._address = None
29
+ self._owner_address = None
30
+
31
+ def load(
32
+ self,
33
+ name: str | None = None,
34
+ address: Account | int | str | None = None,
35
+ owner_address: Account | int | str | None = None
36
+ ):
37
+ """
38
+
39
+ Load a contract details using it's registered name or directly using it's known address.
40
+
41
+ :param str name: Name of the contract that has been registered.
42
+ If provided the address and owner_address of the registration is stored within this object
43
+
44
+ :param str, int, Account address: Address of the contract, if the name is not known,
45
+ then you can provide the actual address of the contract.
46
+
47
+ :param str, int, Account owner_address: If the contract is registered the owner address of the registration.
48
+
49
+ :returns int The address of the resolved contract
50
+
51
+ """
52
+ if name:
53
+ address = self.resolve_address(name)
54
+ owner_address = self.resolve_owner_address(name)
55
+ self._name = name
56
+
57
+ if address is None:
58
+ raise ValueError('no contract found')
59
+
60
+ if owner_address is None:
61
+ owner_address = address
62
+
63
+ self._address = Account.to_address(address)
64
+ self._owner_address = Account.to_address(owner_address)
65
+ return self._address
66
+
67
+ def deploy(
68
+ self,
69
+ account: Account,
70
+ text: str | None = None,
71
+ filename: str | None = None,
72
+ name: str | None = None,
73
+ owner_account: Account | None = None
74
+ ):
75
+ """
76
+
77
+ Deploy a new/updated contract on the Convex network.
78
+
79
+ :param Account account: Account to use to deploy the contract
80
+
81
+ :param str text: Contract text to deploy
82
+
83
+ :param str filename: Filename of the contract to deploy
84
+
85
+ :param str name: Name of the contract to register
86
+
87
+ :param Account owner_account: Optional owner account of the registration.
88
+ If not provided then the Account will be used.
89
+
90
+ :returns Address of the new contract
91
+
92
+ """
93
+ if filename:
94
+ with open(filename, 'r') as fp:
95
+ text = fp.read()
96
+ if text is None:
97
+ raise ValueError('You need to provide a contract filename or text to deploy')
98
+ deploy_line = f"""
99
+ (deploy
100
+ (quote
101
+ (do
102
+ {text}
103
+ )
104
+ )
105
+ )
106
+ """
107
+ result = self._convex.transact(deploy_line, account)
108
+ if result is not None and result.value:
109
+ address = Account.to_address(result.value)
110
+ if name:
111
+ if owner_account is None:
112
+ owner_account = account
113
+ self._convex.registry.register(name, address, owner_account)
114
+ return address
115
+
116
+ def register_contract_name(self, name: str, address: int, account: Account):
117
+ """
118
+
119
+ Register a contract address with a resolvable name. This name can be used on the Convex network to resolve
120
+ to the contract address.
121
+
122
+ :param str name: Name to register.
123
+
124
+ :param str, int, Account address: Address to use to assign with the name.
125
+
126
+ :param Account account: Account who owns the registration.
127
+
128
+ :returns Result from the register transaction
129
+
130
+ """
131
+ return self._convex.registry.register(name, address, account)
132
+
133
+ def transact(self, transaction: str, account: Account):
134
+ """
135
+
136
+ Submit a transaction to the contract. You need to run `load` before calling this method.
137
+
138
+ :param str transaction: Transaction to submit to the contract.
139
+
140
+ :param Account account: Account to pay for the transaction.
141
+
142
+ :returns The transaction result.
143
+
144
+ """
145
+ if not self._address:
146
+ raise ValueError(f'No contract address found for {self._name}')
147
+ return self._convex.transact(f'(call #{self._address} {transaction})', account)
148
+
149
+ def query(self, transaction: str, account_address: Account | int | str | None = None):
150
+ """
151
+
152
+ Sends a query to the contract.
153
+
154
+ :param str transaction: The transaction query to send to the contract
155
+
156
+ :param str, int, Account account_address: The address to provide as the sender for this query.
157
+
158
+ :returns The query result
159
+
160
+ """
161
+ if not self._address:
162
+ raise ValueError(f'No contract address found for {self._name}')
163
+ if account_address is not None:
164
+ account_address = Account.to_address(account_address)
165
+ if account_address is None:
166
+ account_address = self._address
167
+ return self._convex.query(f'(call #{self._address} {transaction})', account_address)
168
+
169
+ def resolve_address(self, name: str):
170
+ """
171
+
172
+ Return an address from a registered name.
173
+
174
+ """
175
+ return self._convex.registry.resolve_address(name)
176
+
177
+ def resolve_owner_address(self, name: str):
178
+ """
179
+
180
+ Returns the register owner of a registered name.
181
+
182
+ """
183
+ return self._convex.registry.resolve_owner(name)
184
+
185
+ @property
186
+ def is_registered(self) -> bool:
187
+ return self._address is not None
188
+
189
+ @property
190
+ def address(self):
191
+ return self._address
192
+
193
+ @property
194
+ def owner_address(self):
195
+ return self._owner_address
196
+
197
+ @property
198
+ def name(self):
199
+ return self._name
200
+
201
+ @staticmethod
202
+ def escape_string(text: str) -> str:
203
+ """
204
+ Escape any string and replace quote chars with leading escape chars
205
+
206
+ """
207
+ escape_text = re.sub('\\\\', '\\\\\\\\', text)
208
+ escape_text = re.sub('"', '\\"', escape_text)
209
+ escape_text = re.sub('\n', '\\\\n', escape_text)
210
+ escape_text = re.sub('\t', '\\\\t', escape_text)
211
+ return escape_text