diff --git a/Cargo.lock b/Cargo.lock
index 4a5a511..1a8a720 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -419,6 +419,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer 0.10.4",
"crypto-common",
+ "subtle",
]
[[package]]
@@ -734,6 +735,15 @@ dependencies = [
"digest 0.9.0",
]
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest 0.10.7",
+]
+
[[package]]
name = "hmac-drbg"
version = "0.3.0"
@@ -741,9 +751,15 @@ source = "git+https://github.com/Rexagon/rust-hmac-drbg#c8634165e88fafdda5f0702f
dependencies = [
"digest 0.9.0",
"generic-array",
- "hmac",
+ "hmac 0.11.0",
]
+[[package]]
+name = "hmac-sha512"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77e806677ce663d0a199541030c816847b36e8dc095f70dae4a4f4ad63da5383"
+
[[package]]
name = "http"
version = "0.2.12"
@@ -1013,7 +1029,7 @@ dependencies = [
[[package]]
name = "nekoton"
version = "0.13.1"
-source = "git+https://github.com/broxus/nekoton.git#c933b4632756de787eda244a31ca020ffe4c644a"
+source = "git+https://github.com/broxus/nekoton.git#9b79453fdf276df45474d858d7789e48d0faaeee"
dependencies = [
"anyhow",
"async-trait",
@@ -1027,7 +1043,7 @@ dependencies = [
"futures-util",
"getrandom",
"hex",
- "hmac",
+ "hmac 0.11.0",
"log",
"nekoton-abi",
"nekoton-contracts",
@@ -1036,13 +1052,14 @@ dependencies = [
"num-bigint",
"once_cell",
"parking_lot",
- "pbkdf2",
+ "pbkdf2 0.12.2",
"quick_cache",
"rand",
"secstr",
"serde",
"serde_json",
- "sha2 0.9.9",
+ "sha2 0.10.9",
+ "slip10_ed25519",
"thiserror 1.0.63",
"tiny-bip39",
"tiny-hderive",
@@ -1058,7 +1075,7 @@ dependencies = [
[[package]]
name = "nekoton-abi"
version = "0.13.0"
-source = "git+https://github.com/broxus/nekoton.git#c933b4632756de787eda244a31ca020ffe4c644a"
+source = "git+https://github.com/broxus/nekoton.git#9b79453fdf276df45474d858d7789e48d0faaeee"
dependencies = [
"anyhow",
"base64 0.13.1",
@@ -1085,10 +1102,11 @@ dependencies = [
[[package]]
name = "nekoton-contracts"
version = "0.13.0"
-source = "git+https://github.com/broxus/nekoton.git#c933b4632756de787eda244a31ca020ffe4c644a"
+source = "git+https://github.com/broxus/nekoton.git#9b79453fdf276df45474d858d7789e48d0faaeee"
dependencies = [
"anyhow",
"nekoton-abi",
+ "nekoton-jetton",
"nekoton-utils",
"once_cell",
"serde",
@@ -1101,7 +1119,7 @@ dependencies = [
[[package]]
name = "nekoton-derive"
version = "0.13.0"
-source = "git+https://github.com/broxus/nekoton.git#c933b4632756de787eda244a31ca020ffe4c644a"
+source = "git+https://github.com/broxus/nekoton.git#9b79453fdf276df45474d858d7789e48d0faaeee"
dependencies = [
"either",
"proc-macro2",
@@ -1109,10 +1127,27 @@ dependencies = [
"syn 1.0.109",
]
+[[package]]
+name = "nekoton-jetton"
+version = "0.13.0"
+source = "git+https://github.com/broxus/nekoton.git#9b79453fdf276df45474d858d7789e48d0faaeee"
+dependencies = [
+ "anyhow",
+ "lazy_static",
+ "nekoton-utils",
+ "num-bigint",
+ "num-traits",
+ "serde",
+ "sha2 0.10.9",
+ "ton_abi",
+ "ton_block",
+ "ton_types",
+]
+
[[package]]
name = "nekoton-proto"
version = "0.1.0"
-source = "git+https://github.com/broxus/nekoton.git#c933b4632756de787eda244a31ca020ffe4c644a"
+source = "git+https://github.com/broxus/nekoton.git#9b79453fdf276df45474d858d7789e48d0faaeee"
dependencies = [
"anyhow",
"nekoton-abi",
@@ -1123,7 +1158,7 @@ dependencies = [
[[package]]
name = "nekoton-python"
-version = "0.1.23"
+version = "0.1.24"
dependencies = [
"ahash",
"anyhow",
@@ -1134,14 +1169,15 @@ dependencies = [
"everscale-asm",
"everscale-types",
"hex",
- "hmac",
+ "hmac 0.11.0",
"log",
"nekoton",
"nekoton-transport",
"num-bigint",
+ "num-traits",
"once_cell",
"parking_lot",
- "pbkdf2",
+ "pbkdf2 0.9.0",
"pyo3",
"pyo3-asyncio",
"pyo3-log",
@@ -1157,12 +1193,13 @@ dependencies = [
"ton_block",
"ton_executor",
"ton_types",
+ "ton_vm",
]
[[package]]
name = "nekoton-transport"
version = "0.13.0"
-source = "git+https://github.com/broxus/nekoton.git#c933b4632756de787eda244a31ca020ffe4c644a"
+source = "git+https://github.com/broxus/nekoton.git#9b79453fdf276df45474d858d7789e48d0faaeee"
dependencies = [
"anyhow",
"async-trait",
@@ -1173,6 +1210,7 @@ dependencies = [
"nekoton-utils",
"reqwest",
"serde",
+ "serde_json",
"thiserror 1.0.63",
"tokio",
]
@@ -1180,18 +1218,18 @@ dependencies = [
[[package]]
name = "nekoton-utils"
version = "0.13.0"
-source = "git+https://github.com/broxus/nekoton.git#c933b4632756de787eda244a31ca020ffe4c644a"
+source = "git+https://github.com/broxus/nekoton.git#9b79453fdf276df45474d858d7789e48d0faaeee"
dependencies = [
"anyhow",
"base64 0.13.1",
"chacha20poly1305",
"ed25519-dalek",
"hex",
- "hmac",
- "pbkdf2",
+ "hmac 0.11.0",
+ "pbkdf2 0.12.2",
"secstr",
"serde",
- "sha2 0.9.9",
+ "sha2 0.10.9",
"thiserror 1.0.63",
"ton_block",
"ton_types",
@@ -1347,11 +1385,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f05894bce6a1ba4be299d0c5f29563e08af2bc18bb7d48313113bed71e904739"
dependencies = [
"crypto-mac",
- "hmac",
+ "hmac 0.11.0",
"password-hash",
"sha2 0.9.9",
]
+[[package]]
+name = "pbkdf2"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
+dependencies = [
+ "digest 0.10.7",
+ "hmac 0.12.1",
+]
+
[[package]]
name = "percent-encoding"
version = "2.3.1"
@@ -1842,6 +1890,15 @@ dependencies = [
"autocfg",
]
+[[package]]
+name = "slip10_ed25519"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4be0ff28bf14f9610a342169084e87a4f435ad798ec528dc7579a3678fa9dc9a"
+dependencies = [
+ "hmac-sha512",
+]
+
[[package]]
name = "smallvec"
version = "1.13.2"
@@ -1990,9 +2047,9 @@ version = "0.8.0"
source = "git+https://github.com/broxus/tiny-bip39.git#d2a73124c2fbead4f969f8a5e075ee22040f63cc"
dependencies = [
"anyhow",
- "hmac",
+ "hmac 0.11.0",
"once_cell",
- "pbkdf2",
+ "pbkdf2 0.9.0",
"rand",
"rustc-hash",
"sha2 0.9.9",
@@ -2007,7 +2064,7 @@ version = "0.3.0"
source = "git+https://github.com/broxus/tiny-hderive.git#050986d85711497076ba552ce53806885274a4d2"
dependencies = [
"base58",
- "hmac",
+ "hmac 0.11.0",
"libsecp256k1",
"memzero",
"sha2 0.9.9",
@@ -2094,7 +2151,7 @@ dependencies = [
[[package]]
name = "ton_abi"
version = "2.1.0"
-source = "git+https://github.com/broxus/ton-labs-abi.git#b8834529ef8fa121d534fca6554c0e95d4019998"
+source = "git+https://github.com/broxus/ton-labs-abi.git#7d84f87a1799b727e33f9b09c8e38c764fbd5c68"
dependencies = [
"anyhow",
"base64 0.13.1",
@@ -2116,7 +2173,7 @@ dependencies = [
[[package]]
name = "ton_block"
version = "1.9.73"
-source = "git+https://github.com/broxus/ton-labs-block.git#5c4e4f84cebaf34254fd97523d1fc83d7fbe2d91"
+source = "git+https://github.com/broxus/ton-labs-block.git#a4fd60ccd6c48e00863dfcf402cb1c045d92a1a3"
dependencies = [
"anyhow",
"base64 0.13.1",
@@ -2138,7 +2195,7 @@ dependencies = [
[[package]]
name = "ton_executor"
version = "1.15.54"
-source = "git+https://github.com/broxus/ton-labs-executor.git#2a38890d53f9c3dad84b3fb9a58e3bb62ba20f44"
+source = "git+https://github.com/broxus/ton-labs-executor.git#8cfdfbac2af31d40bf3926b01aeba7ca5d75c214"
dependencies = [
"anyhow",
"log",
@@ -2151,7 +2208,7 @@ dependencies = [
[[package]]
name = "ton_types"
version = "1.10.2"
-source = "git+https://github.com/broxus/ton-labs-types.git#3324562d7ff1ebec66d996128573966c1b53862b"
+source = "git+https://github.com/broxus/ton-labs-types.git#8556b60547a20f16d50abcab084479d0c9db3756"
dependencies = [
"anyhow",
"base64 0.13.1",
@@ -2173,7 +2230,7 @@ dependencies = [
[[package]]
name = "ton_vm"
version = "1.8.29"
-source = "git+https://github.com/broxus/ton-labs-vm.git#41a85bcde18bc524c18448ffc6aea35aa383c54a"
+source = "git+https://github.com/broxus/ton-labs-vm.git#e693bd7f7a13624503801690a0b70ea5f9b930bd"
dependencies = [
"anyhow",
"ed25519",
diff --git a/Cargo.toml b/Cargo.toml
index c48ae21..4bbd586 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "nekoton-python"
-version = "0.1.23"
+version = "0.1.24"
edition = "2021"
[lib]
@@ -17,6 +17,7 @@ hex = "0.4"
hmac = "0.11"
log = "0.4"
num-bigint = "0.4"
+num-traits = "0.2"
once_cell = "1.17"
parking_lot = "0.12"
pbkdf2 = "0.9"
@@ -35,9 +36,12 @@ tiny-bip39 = { git = "https://github.com/broxus/tiny-bip39.git", default-feature
tiny-hderive = { git = "https://github.com/broxus/tiny-hderive.git" }
ton_abi = { git = "https://github.com/broxus/ton-labs-abi.git" }
-ton_block = { git = "https://github.com/broxus/ton-labs-block.git", features = ["venom"] }
+ton_block = { git = "https://github.com/broxus/ton-labs-block.git", features = [
+ "venom",
+] }
ton_types = { git = "https://github.com/broxus/ton-labs-types.git" }
ton_executor = { git = "https://github.com/broxus/ton-labs-executor.git" }
+ton_vm = { git = "https://github.com/broxus/ton-labs-vm.git" }
everscale-asm = { git = "https://github.com/broxus/everscale-asm.git", rev = "bbd284a72676300c89ab074bd39cd91fde21d597" }
everscale-types = { version = "0.1.2", default-features = false }
diff --git a/README.md b/README.md
index 02f3ffd..df86c2d 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,3 @@
-
-
-
-
-
-
# nekoton-python [![Latest Version]][pypi.org]
Python bindings for Nekoton
@@ -35,7 +29,7 @@ giver_abi = nt.ContractAbi("""{
"events": []
}""")
-send_grams = giver_abi.get_function("sendGrams")
+send_grams = giver_abi.function("sendGrams")
assert send_grams is not None
diff --git a/docs/src/pages/guides/installation-and-quick-start.md b/docs/src/pages/guides/installation-and-quick-start.md
index f9e054d..6b8f4a1 100644
--- a/docs/src/pages/guides/installation-and-quick-start.md
+++ b/docs/src/pages/guides/installation-and-quick-start.md
@@ -46,7 +46,7 @@ giver_abi = nt.ContractAbi("""{
"events": []
}""")
-send_grams = giver_abi.get_function("sendGrams")
+send_grams = giver_abi.function("sendGrams")
assert send_grams is not None
diff --git a/docs/src/pages/guides/working-with-abi.md b/docs/src/pages/guides/working-with-abi.md
index ca373b5..6b321cb 100644
--- a/docs/src/pages/guides/working-with-abi.md
+++ b/docs/src/pages/guides/working-with-abi.md
@@ -143,10 +143,10 @@ public_key, data = abi.decode_init_data(cell)
### Searching for Function ABI
-The `get_function` method of the `ContractAbi` class searches for a function ABI by its name. It returns `FunctionAbi` objects, or `None` if no function with the specified name exists.
+The `function` method of the `ContractAbi` class searches for a function ABI by its name. It returns `FunctionAbi` objects, or `None` if no function with the specified name exists.
```python
-function_abi = abi.get_function("computeSmth")
+function_abi = abi.function("computeSmth")
```
### Encoding Initial Contract Data
@@ -174,7 +174,7 @@ They do not require user interaction and can be called without any parameters or
```python
# Initialize the ABI and get the function
-function_abi = abi.get_function("getComplexState")
+function_abi = abi.function("getComplexState")
# Call the function
result = function_abi.call(account_state, input={})
@@ -194,7 +194,7 @@ If the getter requires parameters, they can be provided in the `input` dictionar
```python
# Initialize the ABI and get the function
-function_abi = abi.get_function("getSecondElementWithPrefix")
+function_abi = abi.function("getSecondElementWithPrefix")
# Call the function with parameters
result = function_abi.call(account_state, input={"prefix": "foo"})
@@ -220,7 +220,7 @@ When a responsible method is called on-chain, it returns the result in an outgoi
```python
# Initialize the ABI and get the function
-function_abi = abi.get_function("computeSmth")
+function_abi = abi.function("computeSmth")
# Call the function with parameters
result = function_abi.call(account_state, input={"offset": 999, "answerId": 42})
@@ -243,7 +243,7 @@ The `encode_external_message` method is utilized to prepare an external message
```python
# Initialize the ABI and get the function
-function_abi = abi.get_function("setVariableExternal")
+function_abi = abi.function("setVariableExternal")
# Define the input parameters
input_params = {"someParam": 66}
@@ -279,7 +279,7 @@ The `encode_internal_message` method is employed to prepare an internal message
```python
# Initialize the ABI and get the function
-function_abi = abi.get_function("setVariable")
+function_abi = abi.function("setVariable")
# Define the input parameters
input_params = {"someParam": 1337}
@@ -386,7 +386,7 @@ They take a `Cell` object and an optional boolean value as arguments, and return
```python
# Setting up the ABI for a specific function.
-function_abi = abi.get_function("setVariable")
+function_abi = abi.function("setVariable")
# Decoding a message body as an input using `decode_input` method from `function_abi` object.
message_body_cell = nt.Cell.decode("te6ccgEBAQEAFgAAKDja0OwAAAAAAAAAAAAAAAAAAAU5")
@@ -404,7 +404,7 @@ print(input_data)
```python
# Setting up the ABI for a specific function.
-function_abi = abi.get_function("setVariable")
+function_abi = abi.function("setVariable")
# Decoding a message body as an output using `decode_output` method from `function_abi` object.
message_body_cell = nt.Cell.decode("te6ccgEBAQEAFgAAKDja0OwAAAAAAAAAAAAAAAAAAAU5")
@@ -437,12 +437,12 @@ The `EventAbi` class is used to interact with the events defined in the smart co
### Searching for Event ABI
-The `get_event` method of the `ContractAbi` class searches for an event ABI by its name.
+The `event` method of the `ContractAbi` class searches for an event ABI by its name.
It returns `EventAbi` objects, or `None` if no event with the specified name exists.
```python
-# Searching for an event ABI by its name using `get_event` method of `abi` object.
-event_abi = abi.get_event("StateChanged")
+# Searching for an event ABI by its name using `event` method of `abi` object.
+event_abi = abi.event("StateChanged")
print(event_abi)
```
@@ -458,8 +458,8 @@ print(event_abi)
The `decode_message` and `decode_message_body` methods decode event data from a message or a message body. They take a `Message` or `Cell` object as an argument respectively, and return a dictionary with the decoded data.
```python
-# Firstly, we retrieve the ABI for a specific event by calling the `get_event` method.
-event_abi = abi.get_event("StateChanged")
+# Firstly, we retrieve the ABI for a specific event by calling the `event` method.
+event_abi = abi.event("StateChanged")
# Here, we decode two different message bodies (as 'Cell' objects) to extract the data they contain.
message_body = nt.Cell.decode("te6ccgEBAgEAEQABEFM5yKUAAAFRAQAIdGVzdA==")
diff --git a/examples/giver.py b/examples/giver.py
index 58d96c1..00091a6 100644
--- a/examples/giver.py
+++ b/examples/giver.py
@@ -13,8 +13,7 @@
"events": []
}""")
-send_grams = giver_abi.get_function("sendGrams")
-assert send_grams is not None
+send_grams = giver_abi.function("sendGrams")
class Giver:
@@ -34,7 +33,7 @@ async def give(self, target: nt.Address, amount: nt.Tokens):
"dest": target,
"amount": amount,
},
- public_key=None
+ public_key=None,
).without_signature()
# Send external message
diff --git a/examples/wallet.py b/examples/wallet.py
index 414827d..5caaa60 100644
--- a/examples/wallet.py
+++ b/examples/wallet.py
@@ -20,16 +20,18 @@
"events": []
}""")
-send_transaction = wallet_abi.get_function("sendTransaction")
-assert send_transaction is not None
+send_transaction = wallet_abi.function("sendTransaction")
wallet_code = nt.Cell.decode(
- 'te6cckEBBgEA/AABFP8A9KQT9LzyyAsBAgEgAgMABNIwAubycdcBAcAA8nqDCNcY7UTQgwfXAdcLP8j4KM8WI88WyfkAA3HXAQHDAJqDB9cBURO68uBk3oBA1wGAINcBgCDXAVQWdfkQ8qj4I7vyeWa++COBBwiggQPoqFIgvLHydAIgghBM7mRsuuMPAcjL/8s/ye1UBAUAmDAC10zQ+kCDBtcBcdcBeNcB10z4AHCAEASqAhSxyMsFUAXPFlAD+gLLaSLQIc8xIddJoIQJuZgzcAHLAFjPFpcwcQHLABLM4skB+wAAPoIQFp4+EbqOEfgAApMg10qXeNcB1AL7AOjRkzLyPOI+zYS/')
+ "te6cckEBBgEA/AABFP8A9KQT9LzyyAsBAgEgAgMABNIwAubycdcBAcAA8nqDCNcY7UTQgwfXAdcLP8j4KM8WI88WyfkAA3HXAQHDAJqDB9cBURO68uBk3oBA1wGAINcBgCDXAVQWdfkQ8qj4I7vyeWa++COBBwiggQPoqFIgvLHydAIgghBM7mRsuuMPAcjL/8s/ye1UBAUAmDAC10zQ+kCDBtcBcdcBeNcB10z4AHCAEASqAhSxyMsFUAXPFlAD+gLLaSLQIc8xIddJoIQJuZgzcAHLAFjPFpcwcQHLABLM4skB+wAAPoIQFp4+EbqOEfgAApMg10qXeNcB1AL7AOjRkzLyPOI+zYS/"
+)
class EverWallet:
@classmethod
- def compute_address(cls, public_key: nt.PublicKey, workchain: int = 0) -> nt.Address:
+ def compute_address(
+ cls, public_key: nt.PublicKey, workchain: int = 0
+ ) -> nt.Address:
return cls.compute_state_init(public_key).compute_address(workchain)
@staticmethod
@@ -39,7 +41,9 @@ def compute_state_init(public_key: nt.PublicKey) -> nt.StateInit:
data_builder.store_u64(0)
return nt.StateInit(wallet_code, data_builder.build())
- def __init__(self, transport: nt.Transport, keypair: nt.KeyPair, workchain: int = 0):
+ def __init__(
+ self, transport: nt.Transport, keypair: nt.KeyPair, workchain: int = 0
+ ):
state_init = self.compute_state_init(keypair.public_key)
self._initialized = False
@@ -52,10 +56,12 @@ def __init__(self, transport: nt.Transport, keypair: nt.KeyPair, workchain: int
def address(self) -> nt.Address:
return self._address
- async def send(self, dst: nt.Address, value: nt.Tokens, payload: nt.Cell, bounce: bool = False) -> nt.Transaction:
+ async def send(
+ self, dst: nt.Address, value: nt.Tokens, payload: nt.Cell, bounce: bool = False
+ ) -> nt.Transaction:
state_init = await self.__get_state_init()
- signature_id = await self._transport.get_signature_id()
+ context = await self._transport.get_signature_context()
external_message = send_transaction.encode_external_message(
self._address,
@@ -64,11 +70,11 @@ async def send(self, dst: nt.Address, value: nt.Tokens, payload: nt.Cell, bounce
"value": value,
"bounce": bounce,
"flags": 3,
- "payload": payload
+ "payload": payload,
},
public_key=self._keypair.public_key,
- state_init=state_init
- ).sign(self._keypair, signature_id)
+ state_init=state_init,
+ ).sign(self._keypair, context)
tx = await self._transport.send_external_message(external_message)
if tx is None:
@@ -90,7 +96,10 @@ async def __get_state_init(self) -> Optional[nt.StateInit]:
return None
account_state = await self.get_account_state()
- if account_state is not None and account_state.status == nt.AccountStatus.Active:
+ if (
+ account_state is not None
+ and account_state.status == nt.AccountStatus.Active
+ ):
self._initialized = True
return None
else:
diff --git a/python/nekoton/__init__.py b/python/nekoton/__init__.py
index ac5e40f..0628ab5 100644
--- a/python/nekoton/__init__.py
+++ b/python/nekoton/__init__.py
@@ -1,4 +1,3 @@
+from . import contracts as contracts
+from . import gql as gql
from .nekoton import *
-
-from . import gql
-from . import contracts
diff --git a/python/nekoton/__main__.py b/python/nekoton/__main__.py
index 06e654b..ffe29fb 100644
--- a/python/nekoton/__main__.py
+++ b/python/nekoton/__main__.py
@@ -1,6 +1,5 @@
-import os
import argparse
-
+import os
from typing import Optional
from . import generator
@@ -21,4 +20,5 @@
if contract_name is None:
contract_name = os.path.basename(args.filename).removesuffix(".abi.json")
+ assert contract_name is not None
print(generator.generate(contract_name, abi))
diff --git a/python/nekoton/contracts/__init__.py b/python/nekoton/contracts/__init__.py
index 705d999..b97e54d 100644
--- a/python/nekoton/contracts/__init__.py
+++ b/python/nekoton/contracts/__init__.py
@@ -1,6 +1,6 @@
-from .base import IGiver
-from .giver_v1 import GiverV1
-from .giver_v2 import GiverV2
-from .ever_wallet import EverWallet
-from .walletv3 import WalletV3
-from .highload_wallet_v2 import HighloadWalletV2
+from .base import IGiver as IGiver
+from .ever_wallet import EverWallet as EverWallet
+from .giver_v1 import GiverV1 as GiverV1
+from .giver_v2 import GiverV2 as GiverV2
+from .highload_wallet_v2 import HighloadWalletV2 as HighloadWalletV2
+from .walletv3 import WalletV3 as WalletV3
diff --git a/python/nekoton/contracts/base.py b/python/nekoton/contracts/base.py
index 48d26fe..3245613 100644
--- a/python/nekoton/contracts/base.py
+++ b/python/nekoton/contracts/base.py
@@ -1,4 +1,4 @@
-import nekoton as _nt
+import nekoton.nekoton as _nt
class IGiver:
diff --git a/python/nekoton/contracts/ever_wallet.py b/python/nekoton/contracts/ever_wallet.py
index c6072f4..0d0c0bd 100644
--- a/python/nekoton/contracts/ever_wallet.py
+++ b/python/nekoton/contracts/ever_wallet.py
@@ -1,8 +1,8 @@
-from typing import Optional, List
+from typing import List, Optional
-from . import IGiver
-import nekoton as _nt
+import nekoton.nekoton as _nt
+from .base import IGiver
_wallet_abi = _nt.ContractAbi("""{
"ABI version": 2,
@@ -79,13 +79,11 @@
}
""")
-_send_transaction = _wallet_abi.get_function("sendTransaction")
-assert _send_transaction is not None
+_send_transaction = _wallet_abi.function("sendTransaction")
-_send_transaction_raw = list()
+_send_transaction_raw: List[_nt.FunctionAbi] = list()
for i in range(4):
- abi = _wallet_abi.get_function(f"sendTransactionRaw{i}")
- assert abi is not None
+ abi = _wallet_abi.function(f"sendTransactionRaw{i}")
_send_transaction_raw.append(abi)
_wallet_code = _nt.Cell.decode(
diff --git a/python/nekoton/contracts/giver_v1.py b/python/nekoton/contracts/giver_v1.py
index 8a57965..c9f4ac5 100644
--- a/python/nekoton/contracts/giver_v1.py
+++ b/python/nekoton/contracts/giver_v1.py
@@ -1,7 +1,8 @@
from __future__ import annotations
-from . import IGiver
-import nekoton as _nt
+import nekoton.nekoton as _nt
+
+from .base import IGiver
_giver_v1_abi = _nt.ContractAbi("""{
"ABI version": 1,
@@ -20,8 +21,8 @@
"events": []
}""")
-_giver_v1_constructor = _giver_v1_abi.get_function("constructor")
-_giver_v1_send_grams = _giver_v1_abi.get_function("sendGrams")
+_giver_v1_constructor = _giver_v1_abi.function("constructor")
+_giver_v1_send_grams = _giver_v1_abi.function("sendGrams")
_giver_v1_tvc = "te6ccgECJQEABaMAAgE0BgEBAcACAgPPIAUDAQHeBAAD0CAAQdgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAIo/wAgwAH0pCBYkvSg4YrtU1gw9KATBwEK9KQg9KEIAgPNQBAJAgHODQoCASAMCwAHDDbMIAAdPAZIbzyvCEhcHHwCl8CgAgEgDw4AASAA1T++wFkZWNvZGVfYWRkciD6QDL6QiBvECByuiFzurHy4H0hbxFu8uB9yHTPCwIibxLPCgcibxMicrqWI28TIs4ynyGBAQAi10mhz0AyICLOMuL+/AFkZWNvZGVfYWRkcjAhydAlVUFfBdswgAgEgEhEAK6T/fYCzsrovsTC2MLcxsvwTt4htmEAApaV/fYCwsa+6OTC3ObMyuWQ5Z6ARZ4UAOOegfBRnixJnixH9ATjnoDh9ATh9AUAgZ6B8EeeFj7lnoBBkkX2Af3+AsLGvujkwtzmzMrkvsrcyL4LAAgEgGhQB4P/+/QFtYWluX2V4dGVybmFsIY5Z/vwBZ2V0X3NyY19hZGRyINAg0wAycL2OGv79AWdldF9zcmNfYWRkcjBwyMnQVRFfAtsw4CBy1yExINMAMiH6QDP+/QFnZXRfc3JjX2FkZHIxISFVMV8E2zDYMSEVAfiOdf7+AWdldF9tc2dfcHVia2V5IMcCjhb+/wFnZXRfbXNnX3B1YmtleTFwMdsw4NUgxwGOF/7/AWdldF9tc2dfcHVia2V5MnAxMdsw4CCBAgDXIdcL/yL5ASIi+RDyqP7/AWdldF9tc2dfcHVia2V5MyADXwPbMNgixwKzFgHMlCLUMTPeJCIijjj++QFzdG9yZV9zaWdvACFvjCJvjCNvjO1HIW+M7UTQ9AVvjCDtV/79AXN0b3JlX3NpZ19lbmRfBdgixwGOE/78AW1zZ19pc19lbXB0eV8G2zDgItMfNCPTPzUgFwF2joDYji/+/gFtYWluX2V4dGVybmFsMiQiVXFfCPFAAf7+AW1haW5fZXh0ZXJuYWwzXwjbMOCAfPLwXwgYAf7++wFyZXBsYXlfcHJvdHBwcO1E0CD0BDI0IIEAgNdFmiDTPzIzINM/MjKWgggbd0Ay4iIluSX4I4ED6KgkoLmwjinIJAH0ACXPCz8izws/Ic8WIMntVP78AXJlcGxheV9wcm90Mn8GXwbbMOD+/AFyZXBsYXlfcHJvdDNwBV8FGQAE2zACASAcGwAPvOP3EDmG2YQCASAeHQCJuyXMvJ+ADwINM/MPAi/vwBcHVzaHBkYzd0b2M07UTQ9AHI7UdvEgH0ACHPFiDJ7VT+/QFwdXNocGRjN3RvYzQwXwLbMIAgEgIh8BCbiJACdQIAH+/v0BY29uc3RyX3Byb3RfMHBwgggbd0DtRNAg9AQyNCCBAIDXRY4UINI/MjMg0j8yMiBx10WUgHvy8N7eyCQB9AAjzws/Is8LP3HPQSHPFiDJ7VT+/QFjb25zdHJfcHJvdF8xXwX4ADDwIf78AXB1c2hwZGM3dG9jNO1E0PQByCEARO1HbxIB9AAhzxYgye1U/v0BcHVzaHBkYzd0b2M0MF8C2zAB4tz+/QFtYWluX2ludGVybmFsIY5Z/vwBZ2V0X3NyY19hZGRyINAg0wAycL2OGv79AWdldF9zcmNfYWRkcjBwyMnQVRFfAtsw4CBy1yExINMAMiH6QDP+/QFnZXRfc3JjX2FkZHIxISFVMV8E2zDYJCFwIwHqjjj++QFzdG9yZV9zaWdvACFvjCJvjCNvjO1HIW+M7UTQ9AVvjCDtV/79AXN0b3JlX3NpZ19lbmRfBdgixwCOHCFwuo4SIoIQXH7iB1VRXwbxQAFfBtsw4F8G2zDg/v4BbWFpbl9pbnRlcm5hbDEi0x80InG6JAA2niCAI1VhXwfxQAFfB9sw4CMhVWFfB/FAAV8H"
@@ -55,6 +56,10 @@ async def deploy(
raise RuntimeError("Message expired")
await transport.trace_transaction(tx).wait()
+ state = await transport.get_account_state(address)
+ if state is None:
+ raise RuntimeError("Account didn't receive funds")
+
# Deploy account
if state.status == _nt.AccountStatus.Active:
return GiverV1(transport, workchain)
@@ -63,6 +68,9 @@ async def deploy(
elif (
state.status == _nt.AccountStatus.Uninit and state.balance < initial_balance
):
+ if other_giver is None:
+ raise RuntimeError("Account does not have enough balance")
+
tx = await other_giver.give(address, initial_balance)
if tx is None:
raise RuntimeError("Message expired")
diff --git a/python/nekoton/contracts/giver_v2.py b/python/nekoton/contracts/giver_v2.py
index 99dca02..9ae9617 100644
--- a/python/nekoton/contracts/giver_v2.py
+++ b/python/nekoton/contracts/giver_v2.py
@@ -1,7 +1,8 @@
from __future__ import annotations
-from . import IGiver
-import nekoton as _nt
+import nekoton.nekoton as _nt
+
+from .base import IGiver
_giver_v2_abi = _nt.ContractAbi("""{
"ABI version": 2,
@@ -22,8 +23,8 @@
"events": []
}""")
-_giver_v2_constructor = _giver_v2_abi.get_function("constructor")
-_giver_v2_send_grams = _giver_v2_abi.get_function("sendTransaction")
+_giver_v2_constructor = _giver_v2_abi.function("constructor")
+_giver_v2_send_grams = _giver_v2_abi.function("sendTransaction")
_giver_v2_tvc = "te6ccgECIAEAA6YAAgE0BgEBAcACAgPPIAUDAQHeBAAD0CAAQdgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAIm/wD0pCAiwAGS9KDhiu1TWDD0oQkHAQr0pCD0oQgAAAIBIA0KAQL/CwH+fyHtRNAg10nCAZ/T/9MA9AX4an/4Yfhm+GKOG/QFbfhqcAGAQPQO8r3XC//4YnD4Y3D4Zn/4YeLTAAGOEoECANcYIPkBWPhCIPhl+RDyqN4j+EUgbpIwcN74Qrry4GUh0z/THzQg+CO88rki+QAg+EqBAQD0DiCRMd7y0Gb4AAwANiD4SiPIyz9ZgQEA9EP4al8E0x8B8AH4R27yfAIBIBQOAgFYEg8BCbjomPxQEAHW+EFujhLtRNDT/9MA9AX4an/4Yfhm+GLe0XBtbwL4SoEBAPSGlQHXCz9/k3BwcOKRII4yXzPIIs8L/yHPCz8xMQFvIiGkA1mAIPRDbwI0IvhKgQEA9HyVAdcLP3+TcHBw4gI1MzHoXwMhwP8RAJiOLiPQ0wH6QDAxyM+HIM6NBAAAAAAAAAAAAAAAAA90TH4ozxYhbyICyx/0AMlx+wDeMMD/jhL4QsjL//hGzwsA+EoB9ADJ7VTef/hnAQm5Fqvn8BMAtvhBbo427UTQINdJwgGf0//TAPQF+Gp/+GH4Zvhijhv0BW34anABgED0DvK91wv/+GJw+GNw+GZ/+GHi3vhG8nNx+GbR+AD4QsjL//hGzwsA+EoB9ADJ7VR/+GcCASAYFQEJuxXvk1gWAbb4QW6OEu1E0NP/0wD0Bfhqf/hh+Gb4Yt76QNcNf5XU0dDTf9/XDACV1NHQ0gDf0VRxIMjPhYDKAHPPQM4B+gKAa89AyXP7APhKgQEA9IaVAdcLP3+TcHBw4pEgFwCEjigh+CO7myL4SoEBAPRbMPhq3iL4SoEBAPR8lQHXCz9/k3BwcOICNTMx6F8G+ELIy//4Rs8LAPhKAfQAye1Uf/hnAgEgGxkBCbjkYYdQGgC++EFujhLtRNDT/9MA9AX4an/4Yfhm+GLe1NH4RSBukjBw3vhCuvLgZfgA+ELIy//4Rs8LAPhKAfQAye1U+A8g+wQg0O0e7VPwAjD4QsjL//hGzwsA+EoB9ADJ7VR/+GcCAtoeHAEBSB0ALPhCyMv/+EbPCwD4SgH0AMntVPgP8gABAUgfAFhwItDWAjHSADDcIccA3CHXDR/yvFMR3cEEIoIQ/////byx8nwB8AH4R27yfA=="
@@ -74,14 +75,21 @@ async def deploy(
raise RuntimeError("Message expired")
await transport.trace_transaction(tx).wait()
+ state = await transport.get_account_state(address)
+ if state is None:
+ raise RuntimeError("Account didn't receive funds")
+
# Deploy account
if state.status == _nt.AccountStatus.Active:
- return GiverV2(transport, workchain)
+ return GiverV2(transport, keypair, workchain)
elif state.status == _nt.AccountStatus.Frozen:
raise RuntimeError("Giver account is frozen")
elif (
state.status == _nt.AccountStatus.Uninit and state.balance < initial_balance
):
+ if other_giver is None:
+ raise RuntimeError("Account does not have enough balance")
+
tx = await other_giver.give(address, initial_balance)
if tx is None:
raise RuntimeError("Message expired")
@@ -99,7 +107,7 @@ async def deploy(
raise RuntimeError("Message expired")
await transport.trace_transaction(tx).wait()
- return GiverV2(transport, workchain)
+ return GiverV2(transport, keypair, workchain)
def __init__(
self, transport: _nt.Transport, keypair: _nt.KeyPair, workchain: int = 0
diff --git a/python/nekoton/contracts/highload_wallet_v2.py b/python/nekoton/contracts/highload_wallet_v2.py
index a13431d..624d9d9 100644
--- a/python/nekoton/contracts/highload_wallet_v2.py
+++ b/python/nekoton/contracts/highload_wallet_v2.py
@@ -1,7 +1,8 @@
-from typing import Optional, List
+from typing import List, Optional
-from . import IGiver
-import nekoton as _nt
+import nekoton.nekoton as _nt
+
+from .base import IGiver
_wallet_code = _nt.Cell.decode(
"te6ccgEBCQEA5QABFP8A9KQT9LzyyAsBAgEgBAIB6vKDCNcYINMf0z/4I6ofUyC58mPtRNDTH9M/0//0BNFTYIBA9A5voTHyYFFzuvKiB/kBVBCH+RDyowL0BNH4AH+OFiGAEPR4b6UgmALTB9QwAfsAkTLiAbPmW4MlochANIBA9EOK5jHIEssfE8s/y//0AMntVAMANCCAQPSWb6UyURCUMFMDud4gkzM2AZIyMOKzAgFICAUCASAHBgBBvl+XaiaGmPmOmf6f+Y+gJoqRBAIHoHN9CYyS2/yV3R8UABe9nOdqJoaa+Y64X/wABNAw"
@@ -9,7 +10,7 @@
_default_wallet_id = 0x00000000
_default_ttl = 60
-_messages_abi = [
+_messages_abi: list[tuple[str, _nt.AbiParam]] = [
(
"messages",
_nt.AbiMap(
@@ -172,10 +173,7 @@ async def __get_state_init(self) -> Optional[_nt.StateInit]:
return None
account_state = await self.get_account_state()
- if (
- account_state is not None
- and account_state.status == _nt.AccountStatus.Active
- ):
+ if account_state is not None and account_state.state_init is not None:
if account_state.state_init.data is None:
raise RuntimeError("Account state does not contain data")
diff --git a/python/nekoton/contracts/walletv3.py b/python/nekoton/contracts/walletv3.py
index 491c304..2f511f9 100644
--- a/python/nekoton/contracts/walletv3.py
+++ b/python/nekoton/contracts/walletv3.py
@@ -1,7 +1,8 @@
-from typing import Optional, List
+from typing import List, Optional
-from . import IGiver
-import nekoton as _nt
+import nekoton.nekoton as _nt
+
+from .base import IGiver
_wallet_code = _nt.Cell.decode(
"te6ccgEBAQEAcQAA3v8AIN0gggFMl7ohggEznLqxn3Gw7UTQ0x/THzHXC//jBOCk8mCDCNcYINMf0x/TH/gjE7vyY+1E0NMf0x/T/9FRMrryoVFEuvKiBPkBVBBV+RDyo/gAkyDXSpbTB9QC+wDo0QGkyMsfyx/L/8ntVA=="
@@ -47,7 +48,6 @@ def __init__(
):
state_init = self.compute_state_init(keypair.public_key, wallet_id)
- self._initialized = False
self._wallet_id = wallet_id
self._transport = transport
self._keypair = keypair
@@ -150,14 +150,8 @@ async def get_balance(self) -> _nt.Tokens:
return state.balance
async def __get_seqno_and_state_init(self) -> tuple[int, Optional[_nt.StateInit]]:
- if self._initialized:
- return None
-
account_state = await self.get_account_state()
- if (
- account_state is not None
- and account_state.status == _nt.AccountStatus.Active
- ):
+ if account_state is not None and account_state.state_init is not None:
if account_state.state_init.data is None:
raise RuntimeError("Account state does not contain data")
@@ -167,7 +161,6 @@ async def __get_seqno_and_state_init(self) -> tuple[int, Optional[_nt.StateInit]
# NOTE: Update wallet_id just in case
self._wallet_id = data.load_u32()
- self._initialized = True
return seqno, None
else:
return 0, self._state_init
diff --git a/python/nekoton/generator/__init__.py b/python/nekoton/generator/__init__.py
index fe55ca2..2a6d40e 100644
--- a/python/nekoton/generator/__init__.py
+++ b/python/nekoton/generator/__init__.py
@@ -1,6 +1,6 @@
import json
import re
-from typing import Optional, List, Dict
+from typing import Dict, List, Optional
from nekoton import ContractAbi
@@ -16,7 +16,9 @@ def __init__(self, name: str, decl: str):
class InternalFunction:
- def __init__(self, abi_name: str, inputs_ty: str, outputs_ty: str, struct: InternalStruct):
+ def __init__(
+ self, abi_name: str, inputs_ty: str, outputs_ty: str, struct: InternalStruct
+ ):
self.abi_name = abi_name
self.inputs_ty = inputs_ty
self.outputs_ty = outputs_ty
@@ -36,7 +38,7 @@ def optional_type(ty: Optional[str]) -> str:
self.head += "):"
self.body = None
- def with_body(self, body) -> 'MethodBuilder':
+ def with_body(self, body) -> "MethodBuilder":
self.body = body
return self
@@ -56,15 +58,17 @@ def __init__(self, name: str) -> None:
self.fields = []
self.methods = []
- def with_base(self, base: str) -> 'ClassBuilder':
+ def with_base(self, base: str) -> "ClassBuilder":
self.derive.append(base)
return self
- def with_field(self, name: str, ty: str) -> 'ClassBuilder':
+ def with_field(self, name: str, ty: str) -> "ClassBuilder":
self.fields.append((name, ty))
return self
- def with_method(self, method: MethodBuilder, attributes: List[str] = []) -> 'ClassBuilder':
+ def with_method(
+ self, method: MethodBuilder, attributes: List[str] = []
+ ) -> "ClassBuilder":
self.methods.append((method, attributes))
return self
@@ -140,7 +144,10 @@ def generate_abi_class(self, name: str, abi: str) -> str:
abi_object = class_name.upper() + "_ABI"
abi_object_decl = '%s = %s(r"""%s""")\n\n' % (
- abi_object, self._from_nekoton.import_ty("ContractAbi"), json.dumps(parsed_abi))
+ abi_object,
+ self._from_nekoton.import_ty("ContractAbi"),
+ json.dumps(parsed_abi),
+ )
result = ClassBuilder(class_name + "Abi")
function_classes_decl = ""
@@ -149,9 +156,9 @@ def generate_abi_class(self, name: str, abi: str) -> str:
function_classes_decl += f"{function_class.struct.decl}\n\n"
member_name = depascalize(pascalize(function_class.abi_name))
- method = MethodBuilder(member_name, {}, function_class.struct.name).with_body(
- f'return {abi_object}.get_function("{function_class.abi_name}")'
- )
+ method = MethodBuilder(
+ member_name, {}, function_class.struct.name
+ ).with_body(f'return {abi_object}.function("{function_class.abi_name}")')
result.with_method(method, ["@staticmethod"])
class_decl = result.generate()
@@ -171,68 +178,93 @@ def generate_function(self, base_class: str, function: dict) -> InternalFunction
outputs = function["outputs"]
name_struct = pascalize(name)
- inputs_ty = self.generate_tuple(inputs, name_struct + "Input", cache_signature=False)
- outputs_ty = self.generate_tuple(outputs, name_struct + "Output", cache_signature=False)
+ inputs_ty = self.generate_tuple(
+ inputs, name_struct + "Input", cache_signature=False
+ )
+ outputs_ty = self.generate_tuple(
+ outputs, name_struct + "Output", cache_signature=False
+ )
function_ty = base_class + pascalize(name) + "Function"
function_call_ty = function_ty + "Call"
function_call_base_ty = self._from_nekoton.import_ty("FunctionCall")
- function_call_input_method = MethodBuilder("input", {"self": None}, inputs_ty).with_body(
- f"return {function_call_base_ty}.input"
- )
- function_call_output_method = MethodBuilder("output", {"self": None}, outputs_ty).with_body(
- f"return {function_call_base_ty}.output"
+ function_call_input_method = MethodBuilder(
+ "input", {"self": None}, inputs_ty
+ ).with_body(f"return {function_call_base_ty}.input")
+ function_call_output_method = MethodBuilder(
+ "output", {"self": None}, outputs_ty
+ ).with_body(f"return {function_call_base_ty}.output")
+ function_call = (
+ ClassBuilder(function_ty + "Call")
+ .with_base(function_call_base_ty)
+ .with_method(function_call_input_method, ["@property"])
+ .with_method(function_call_output_method, ["@property"])
)
- function_call = ClassBuilder(function_ty + "Call").with_base(function_call_base_ty)\
- .with_method(function_call_input_method, ['@property'])\
- .with_method(function_call_output_method, ['@property'])
- self._internal_structs_decl += f"{function_call.generate()}\n\n"
+ self._internal_structs_decl += f"{function_call.generate()}\n\n"
function_abi_ty = self._from_nekoton.import_ty("FunctionAbi")
function_with_args_ty = self._from_nekoton.import_ty("FunctionAbiWithArgs")
- with_args_method = MethodBuilder("with_args", {
- "self": None,
- "args": inputs_ty,
- }, function_with_args_ty).with_body(f"return {function_abi_ty}.with_args(self, args)")
-
- decode_transaction = MethodBuilder("decode_transaction", {
- "self": None,
- "transaction": self._from_nekoton.import_ty("Transaction")
- }, function_call_ty).with_body(f"return {function_abi_ty}.decode_transaction(transaction)")
-
- decode_input_method = MethodBuilder("decode_input", {
- "self": None,
- "message_body": self._from_nekoton.import_ty("Cell"),
- "internal": "bool",
- "allow_partial": f'{self._from_typing.import_ty("Optional")}[bool] = None',
- }, inputs_ty).with_body(
+ with_args_method = MethodBuilder(
+ "with_args",
+ {
+ "self": None,
+ "args": inputs_ty,
+ },
+ function_with_args_ty,
+ ).with_body(f"return {function_abi_ty}.with_args(self, args)")
+
+ decode_transaction = MethodBuilder(
+ "decode_transaction",
+ {"self": None, "transaction": self._from_nekoton.import_ty("Transaction")},
+ function_call_ty,
+ ).with_body(f"return {function_abi_ty}.decode_transaction(transaction)")
+
+ decode_input_method = MethodBuilder(
+ "decode_input",
+ {
+ "self": None,
+ "message_body": self._from_nekoton.import_ty("Cell"),
+ "internal": "bool",
+ "allow_partial": f"{self._from_typing.import_ty('Optional')}[bool] = None",
+ },
+ inputs_ty,
+ ).with_body(
f"return {function_abi_ty}.decode_input(self, message_body, internal, allow_partial)"
)
- decode_output_method = MethodBuilder("decode_output", {
- "self": None,
- "message_body": self._from_nekoton.import_ty("Cell"),
- "allow_partial": f'{self._from_typing.import_ty("Optional")}[bool] = None',
- }, outputs_ty).with_body(
+ decode_output_method = MethodBuilder(
+ "decode_output",
+ {
+ "self": None,
+ "message_body": self._from_nekoton.import_ty("Cell"),
+ "allow_partial": f"{self._from_typing.import_ty('Optional')}[bool] = None",
+ },
+ outputs_ty,
+ ).with_body(
f"return {function_abi_ty}.decode_output(self, message_body, allow_partial)"
)
- result = ClassBuilder(function_ty).with_base(function_abi_ty)\
- .with_method(with_args_method)\
- .with_method(decode_input_method)\
- .with_method(decode_output_method)\
- .with_method(decode_transaction)\
+ result = (
+ ClassBuilder(function_ty)
+ .with_base(function_abi_ty)
+ .with_method(with_args_method)
+ .with_method(decode_input_method)
+ .with_method(decode_output_method)
+ .with_method(decode_transaction)
.generate()
- return InternalFunction(name, inputs_ty, outputs_ty, InternalStruct(function_ty, result))
+ )
+ return InternalFunction(
+ name, inputs_ty, outputs_ty, InternalStruct(function_ty, result)
+ )
def generate_type(self, ty: str, components: Optional[List[dict]]) -> str:
if ty == "":
raise InvalidTypeError(ty)
elif ty.endswith("]"):
- len_idx = ty.rfind('[')
+ len_idx = ty.rfind("[")
if len_idx == -1:
raise InvalidTypeError(ty)
value_ty = self.generate_type(ty[:len_idx], components)
@@ -246,13 +278,13 @@ def generate_type(self, ty: str, components: Optional[List[dict]]) -> str:
elif ty.startswith("optional("):
if not ty.endswith(")"):
raise InvalidTypeError(ty)
- value_ty = self.generate_type(ty[ty.find("(") + 1:-1], components)
+ value_ty = self.generate_type(ty[ty.find("(") + 1 : -1], components)
return "%s[%s]" % (self._from_typing.import_ty("Optional"), value_ty)
elif ty.startswith("ref("):
if not ty.endswith(")"):
raise InvalidTypeError(ty)
- return self.generate_type(ty[ty.find("(") + 1:-1], components)
+ return self.generate_type(ty[ty.find("(") + 1 : -1], components)
elif ty.startswith("map("):
if not ty.endswith(")"):
@@ -264,16 +296,25 @@ def generate_type(self, ty: str, components: Optional[List[dict]]) -> str:
raise InvalidTypeError(ty)
key_ty = self.generate_type(ty[key_ty_idx:delim_idx], None)
- value_ty = self.generate_type(ty[delim_idx + 1:-1], components)
+ value_ty = self.generate_type(ty[delim_idx + 1 : -1], components)
- return "%s[%s, %s]" % (self._from_typing.import_ty("Dict"), key_ty, value_ty)
+ return "%s[%s, %s]" % (
+ self._from_typing.import_ty("Dict"),
+ key_ty,
+ value_ty,
+ )
elif ty == "bool":
return ty
- elif ty.startswith("int") or ty.startswith("uint") or \
- ty.startswith("varint") or ty.startswith("varuint") or \
- ty.startswith("time") or ty.startswith("expire"):
+ elif (
+ ty.startswith("int")
+ or ty.startswith("uint")
+ or ty.startswith("varint")
+ or ty.startswith("varuint")
+ or ty.startswith("time")
+ or ty.startswith("expire")
+ ):
return "int | %s" % self._from_nekoton.import_ty("Tokens")
elif ty == "cell":
@@ -297,7 +338,9 @@ def generate_type(self, ty: str, components: Optional[List[dict]]) -> str:
else:
raise InvalidTypeError(ty)
- def generate_tuple(self, components: List[dict], name: Optional[str], cache_signature: bool) -> str:
+ def generate_tuple(
+ self, components: List[dict], name: Optional[str], cache_signature: bool
+ ) -> str:
type_signature = ""
if cache_signature:
type_signature = compute_tuple_signature(components)
@@ -314,7 +357,9 @@ def generate_tuple(self, components: List[dict], name: Optional[str], cache_sign
field_name = component["name"]
field_ty = component["type"]
field_components = component.get("components")
- result.with_field(field_name, self.generate_type(field_ty, field_components))
+ result.with_field(
+ field_name, self.generate_type(field_ty, field_components)
+ )
if cache_signature:
self._internal_structs[type_signature] = name
@@ -372,7 +417,7 @@ def privatize(ty: str) -> str:
def indent_text(text: str, level: int) -> str:
- indent = ' ' * (4 * level)
+ indent = " " * (4 * level)
lines = text.strip().split("\n")
return "\n".join(f"{indent}{line}" for line in lines)
diff --git a/python/nekoton/gql/__init__.py b/python/nekoton/gql/__init__.py
index 6df0932..5bd4a15 100644
--- a/python/nekoton/gql/__init__.py
+++ b/python/nekoton/gql/__init__.py
@@ -1,10 +1,8 @@
from typing import List as _List
-from nekoton import GqlExprPart
-from . import filters
-from . import msg
-from . import tx
-from . import acc
+from nekoton.nekoton import GqlExprPart
+
+from . import acc, filters, msg, tx
def and_(expressions: str | GqlExprPart | _List[GqlExprPart]) -> GqlExprPart:
@@ -13,7 +11,7 @@ def and_(expressions: str | GqlExprPart | _List[GqlExprPart]) -> GqlExprPart:
if isinstance(expressions, str):
return GqlExprPart(expressions)
else:
- return GqlExprPart(','.join(map(str, expressions)))
+ return GqlExprPart(",".join(map(str, expressions)))
def or_(expressions: _List[str | GqlExprPart | _List[GqlExprPart]]) -> GqlExprPart:
@@ -21,7 +19,7 @@ def or_(expressions: _List[str | GqlExprPart | _List[GqlExprPart]]) -> GqlExprPa
for expr in reversed(expressions):
element = and_(expr)
if last_part is not None:
- last_part = '{},OR:{{{}}}'.format(element, last_part)
+ last_part = GqlExprPart("{},OR:{{{}}}".format(element, last_part))
else:
last_part = element
diff --git a/python/nekoton/gql/acc.py b/python/nekoton/gql/acc.py
index 16c9aa2..66bd2e6 100644
--- a/python/nekoton/gql/acc.py
+++ b/python/nekoton/gql/acc.py
@@ -1,6 +1,10 @@
-from .filters import IntFilter as _IntFilter, OrderBy as _OrderBy, AddressFilter as _AddressFilter, \
- AccountStatusFilter as _AccountStatusFilter, TokensFilter as _TokensFilter, HashFilter as _HashFilter, \
- IntAsStringFilter as _IntAsStringFilter
+from .filters import AccountStatusFilter as _AccountStatusFilter
+from .filters import AddressFilter as _AddressFilter
+from .filters import HashFilter as _HashFilter
+from .filters import IntAsStringFilter as _IntAsStringFilter
+from .filters import IntFilter as _IntFilter
+from .filters import OrderBy as _OrderBy
+from .filters import TokensFilter as _TokensFilter
class WorkchainId(_IntFilter, _OrderBy):
diff --git a/python/nekoton/gql/filters.py b/python/nekoton/gql/filters.py
index 8f5c071..0faee52 100644
--- a/python/nekoton/gql/filters.py
+++ b/python/nekoton/gql/filters.py
@@ -1,7 +1,13 @@
from typing import Iterable as _Iterable
-from nekoton import Address as _Address, Tokens as _Tokens, TransactionType as _TransactionType, MessageType as _MessageType, \
- AccountStatus as _AccountStatus, GqlExprPart
+from nekoton.nekoton import AccountStatus as _AccountStatus
+from nekoton.nekoton import Address as _Address
+from nekoton.nekoton import GqlExprPart
+from nekoton.nekoton import MessageType as _MessageType
+from nekoton.nekoton import Tokens as _Tokens
+from nekoton.nekoton import TransactionType as _TransactionType
+
+# pyright: reportIncompatibleMethodOverride=false
class OrderBy:
@@ -21,9 +27,9 @@ def __init__(self, field: str):
def _op(self, value: bool) -> GqlExprPart:
if value:
- return GqlExprPart('{}:{{eq:true}}'.format(self._field))
+ return GqlExprPart("{}:{{eq:true}}".format(self._field))
else:
- return GqlExprPart('{}:{{eq:false}}'.format(self._field))
+ return GqlExprPart("{}:{{eq:false}}".format(self._field))
def __invert__(self) -> GqlExprPart:
return self._op(False)
@@ -40,16 +46,18 @@ def __init__(self, field: str):
self._field = field
def any_of(self, values: _Iterable[int]) -> GqlExprPart:
- return self._multi_op('in', values)
+ return self._multi_op("in", values)
def not_any_of(self, values: _Iterable[int]) -> GqlExprPart:
- return self._multi_op('notIn', values)
+ return self._multi_op("notIn", values)
def _op(self, op: str, value: int) -> GqlExprPart:
- return GqlExprPart('{}:{{{}:{}}}'.format(self._field, op, value))
+ return GqlExprPart("{}:{{{}:{}}}".format(self._field, op, value))
def _multi_op(self, op: str, values: _Iterable[int]) -> GqlExprPart:
- return GqlExprPart('{}:{{{}:[{}]}}'.format(self._field, op, ','.join(map(str, values))))
+ return GqlExprPart(
+ "{}:{{{}:[{}]}}".format(self._field, op, ",".join(map(str, values)))
+ )
def __eq__(self, other: int) -> GqlExprPart:
return self._op("eq", other)
@@ -72,10 +80,10 @@ def __init__(self, field: str):
self._field = field
def any_of(self, values: _Iterable[str]) -> GqlExprPart:
- return self._multi_op('in', values)
+ return self._multi_op("in", values)
def not_any_of(self, values: _Iterable[str]) -> GqlExprPart:
- return self._multi_op('notIn', values)
+ return self._multi_op("notIn", values)
def _op(self, op: str, value: str) -> GqlExprPart:
return GqlExprPart('{}:{{{}:"{}"}}'.format(self._field, op, value))
@@ -83,7 +91,7 @@ def _op(self, op: str, value: str) -> GqlExprPart:
def _multi_op(self, op: str, values: _Iterable[str]) -> GqlExprPart:
values = '","'.join(values)
if not values:
- return GqlExprPart('{}:{{{}:[]}}'.format(self._field, op))
+ return GqlExprPart("{}:{{{}:[]}}".format(self._field, op))
else:
return GqlExprPart('{}:{{{}:["{}"]}}'.format(self._field, op, values))
@@ -105,10 +113,10 @@ def __le__(self, other: str) -> GqlExprPart:
class IntAsStringFilter(StringFilter):
def any_of(self, values: _Iterable[int | str]) -> GqlExprPart:
- return self._multi_op('in', map(str, values))
+ return self._multi_op("in", map(str, values))
def not_any_of(self, values: _Iterable[int | str]) -> GqlExprPart:
- return self._multi_op('notIn', map(str, values))
+ return self._multi_op("notIn", map(str, values))
def __eq__(self, other: int | str) -> GqlExprPart:
return self._op("eq", str(other))
@@ -135,10 +143,10 @@ def __convert(value: _Tokens | int | str) -> str:
return str(value)
def any_of(self, values: _Iterable[_Tokens | int | str]) -> GqlExprPart:
- return self._multi_op('in', map(TokensFilter.__convert, values))
+ return self._multi_op("in", map(TokensFilter.__convert, values))
def not_any_of(self, values: _Iterable[_Tokens | int | str]) -> GqlExprPart:
- return self._multi_op('notIn', map(TokensFilter.__convert, values))
+ return self._multi_op("notIn", map(TokensFilter.__convert, values))
def __eq__(self, other: _Tokens | int | str) -> GqlExprPart:
return self._op("eq", TokensFilter.__convert(other))
@@ -165,10 +173,10 @@ def __convert(value: bytes | str) -> str:
return value
def any_of(self, values: _Iterable[bytes | str]) -> GqlExprPart:
- return self._multi_op('in', map(HashFilter.__convert, values))
+ return self._multi_op("in", map(HashFilter.__convert, values))
def not_any_of(self, values: _Iterable[bytes | str]) -> GqlExprPart:
- return self._multi_op('notIn', map(HashFilter.__convert, values))
+ return self._multi_op("notIn", map(HashFilter.__convert, values))
def __eq__(self, other: bytes | str) -> GqlExprPart:
return self._op("eq", HashFilter.__convert(other))
@@ -188,10 +196,10 @@ def __le__(self, other: bytes | str) -> GqlExprPart:
class AddressFilter(StringFilter):
def any_of(self, values: _Iterable[_Address | str]) -> GqlExprPart:
- return self._multi_op('in', map(str, values))
+ return self._multi_op("in", map(str, values))
def not_any_of(self, values: _Iterable[_Address | str]) -> GqlExprPart:
- return self._multi_op('notIn', map(str, values))
+ return self._multi_op("notIn", map(str, values))
def __eq__(self, other: _Address | str) -> GqlExprPart:
return self._op("eq", str(other))
@@ -211,10 +219,10 @@ def __le__(self, other: _Address | str) -> GqlExprPart:
class TransactionTypeFilter(IntFilter):
def any_of(self, values: _Iterable[_TransactionType | int]) -> GqlExprPart:
- return self._multi_op('in', map(int, values))
+ return self._multi_op("in", map(int, values))
def not_any_of(self, values: _Iterable[_TransactionType | int]) -> GqlExprPart:
- return self._multi_op('notIn', map(int, values))
+ return self._multi_op("notIn", map(int, values))
def __eq__(self, other: _TransactionType | int) -> GqlExprPart:
return self._op("eq", int(other))
@@ -234,10 +242,10 @@ def __le__(self, other: _TransactionType | int) -> GqlExprPart:
class MessageTypeFilter(IntFilter):
def any_of(self, values: _Iterable[_MessageType | int]) -> GqlExprPart:
- return self._multi_op('in', map(int, values))
+ return self._multi_op("in", map(int, values))
def not_any_of(self, values: _Iterable[_MessageType | int]) -> GqlExprPart:
- return self._multi_op('notIn', map(int, values))
+ return self._multi_op("notIn", map(int, values))
def __eq__(self, other: _MessageType | int) -> GqlExprPart:
return self._op("eq", int(other))
@@ -257,10 +265,10 @@ def __le__(self, other: _MessageType | int) -> GqlExprPart:
class AccountStatusFilter(IntFilter):
def any_of(self, values: _Iterable[_AccountStatus | int]) -> GqlExprPart:
- return self._multi_op('in', map(int, values))
+ return self._multi_op("in", map(int, values))
def not_any_of(self, values: _Iterable[_AccountStatus | int]) -> GqlExprPart:
- return self._multi_op('notIn', map(int, values))
+ return self._multi_op("notIn", map(int, values))
def __eq__(self, other: _AccountStatus | int) -> GqlExprPart:
return self._op("eq", int(other))
diff --git a/python/nekoton/gql/msg.py b/python/nekoton/gql/msg.py
index 34dd020..665f648 100644
--- a/python/nekoton/gql/msg.py
+++ b/python/nekoton/gql/msg.py
@@ -1,6 +1,11 @@
-from .filters import OrderBy as _OrderBy, IntFilter as _IntFilter, HashFilter as _HashFilter, TokensFilter as _TokensFilter, \
- BoolFilter as _BoolFilter, AddressFilter as _AddressFilter, MessageTypeFilter as _MessageTypeFilter, \
- IntAsStringFilter as _IntAsStringFilter
+from .filters import AddressFilter as _AddressFilter
+from .filters import BoolFilter as _BoolFilter
+from .filters import HashFilter as _HashFilter
+from .filters import IntAsStringFilter as _IntAsStringFilter
+from .filters import IntFilter as _IntFilter
+from .filters import MessageTypeFilter as _MessageTypeFilter
+from .filters import OrderBy as _OrderBy
+from .filters import TokensFilter as _TokensFilter
class Id(_HashFilter, _OrderBy):
diff --git a/python/nekoton/gql/tx.py b/python/nekoton/gql/tx.py
index bd5e17a..ddb8608 100644
--- a/python/nekoton/gql/tx.py
+++ b/python/nekoton/gql/tx.py
@@ -1,6 +1,11 @@
-from .filters import IntFilter as _IntFilter, OrderBy as _OrderBy, HashFilter as _HashFilter, BoolFilter as _BoolFilter, \
- AddressFilter as _AddressFilter, TokensFilter as _TokensFilter, IntAsStringFilter as _IntAsStringFilter, \
- TransactionTypeFilter as _TransactionTypeFilter
+from .filters import AddressFilter as _AddressFilter
+from .filters import BoolFilter as _BoolFilter
+from .filters import HashFilter as _HashFilter
+from .filters import IntAsStringFilter as _IntAsStringFilter
+from .filters import IntFilter as _IntFilter
+from .filters import OrderBy as _OrderBy
+from .filters import TokensFilter as _TokensFilter
+from .filters import TransactionTypeFilter as _TransactionTypeFilter
class WorkchainId(_IntFilter, _OrderBy):
diff --git a/python/nekoton/nekoton.pyi b/python/nekoton/nekoton.pyi
index 9ef78ab..48e2b0f 100644
--- a/python/nekoton/nekoton.pyi
+++ b/python/nekoton/nekoton.pyi
@@ -1,13 +1,11 @@
from os import PathLike
-from typing import Any, ClassVar, Optional, List, Tuple, Dict
-
+from typing import Any, ClassVar, Dict, List, Optional, Tuple
#########
## ABI ##
#########
#
-
class TransactionExecutor:
"""
Local transaction executor.
@@ -20,13 +18,14 @@ class TransactionExecutor:
check_signature: bool
"""Whether to require valid signatures."""
- def __init__(self, config: BlockchainConfig, clock: Optional[Clock] = None,
- check_signature: Optional[bool] = None) -> None: ...
-
+ def __init__(
+ self,
+ config: BlockchainConfig,
+ clock: Optional[Clock] = None,
+ check_signature: Optional[bool] = None,
+ ) -> None: ...
def execute(
- self,
- message: Message,
- account: Optional[AccountState] = None
+ self, message: Message, account: Optional[AccountState] = None
) -> Tuple[Transaction, Optional[AccountState]]:
"""
Executes the specified message on account state.
@@ -36,7 +35,6 @@ class TransactionExecutor:
"""
...
-
class ContractAbi:
"""
Parsed contract ABI.
@@ -45,12 +43,11 @@ class ContractAbi:
"""
@staticmethod
- def from_file(file: str | bytes | PathLike[str] | PathLike[bytes]) -> ContractAbi:
+ def from_file(path: str | bytes | PathLike[str] | PathLike[bytes]) -> ContractAbi:
"""Reads ABI from file."""
...
def __init__(self, abi: str) -> None: ...
-
@property
def abi_version(self) -> AbiVersion:
"""TVM ABI version."""
@@ -64,6 +61,14 @@ class ContractAbi:
"""
...
+ def function(self, name: str) -> FunctionAbi:
+ """
+ Searches for the function ABI with the specified name.
+
+ :param name: function name.
+ """
+ ...
+
def get_event(self, name: str) -> Optional[EventAbi]:
"""
Searches for the event ABI with the specified name.
@@ -72,11 +77,35 @@ class ContractAbi:
"""
...
+ def event(self, name: str) -> EventAbi:
+ """
+ Searches for the event ABI with the specified name.
+
+ :param name: event name.
+ """
+ ...
+
+ def get_getter(self, name: str) -> Optional[GetterAbi]:
+ """
+ Searches for the getter ABI with the specified name.
+
+ :param name: getter name.
+ """
+ ...
+
+ def getter(self, name: str) -> GetterAbi:
+ """
+ Searches for the getter ABI with the specified name.
+
+ :param name: getter name.
+ """
+ ...
+
def encode_init_data(
- self,
- data: Dict[str, Any],
- public_key: Optional[PublicKey] = None,
- existing_data: Optional[Cell] = None
+ self,
+ data: Dict[str, Any],
+ public_key: Optional[PublicKey] = None,
+ existing_data: Optional[Cell] = None,
) -> Cell:
"""
Encodes initial contract data using the specified values and public key.
@@ -87,7 +116,9 @@ class ContractAbi:
"""
...
- def decode_init_data(self, data: Cell) -> Tuple[Optional[PublicKey], Dict[str, Any]]:
+ def decode_init_data(
+ self, data: Cell
+ ) -> Tuple[Optional[PublicKey], Dict[str, Any]]:
"""
Decodes initial contract data using the contract ABI.
@@ -95,7 +126,9 @@ class ContractAbi:
"""
...
- def decode_fields(self, data: Cell | AccountState) -> Dict[str, Any]:
+ def decode_fields(
+ self, data: Cell | AccountState, allow_partial: Optional[bool] = None
+ ) -> Dict[str, Any]:
"""
Decodes fields from the contract data.
@@ -103,7 +136,9 @@ class ContractAbi:
"""
...
- def decode_transaction(self, transaction: Transaction) -> Optional[FunctionCallFull]:
+ def decode_transaction(
+ self, transaction: Transaction
+ ) -> Optional[FunctionCallFull]:
"""
Decodes function call and events from the specified transaction.
@@ -111,7 +146,9 @@ class ContractAbi:
"""
...
- def decode_transaction_events(self, transaction: Transaction) -> List[Tuple[EventAbi, Dict[str, Any]]]:
+ def decode_transaction_events(
+ self, transaction: Transaction
+ ) -> List[Tuple[EventAbi, Dict[str, Any]]]:
"""
Decodes only events from the specified transaction.
@@ -119,7 +156,6 @@ class ContractAbi:
"""
...
-
class FunctionAbi:
"""Parsed function ABI."""
@@ -152,11 +188,12 @@ class FunctionAbi:
...
def call(
- self,
- account_state: AccountState,
- input: Dict,
- responsible: Optional[bool] = None,
- clock: Optional[Clock] = None,
+ self,
+ account_state: AccountState,
+ input: Dict,
+ responsible: Optional[bool] = None,
+ clock: Optional[Clock] = None,
+ config: Optional[BlockchainConfig] = None,
) -> ExecutionOutput:
"""
Runs this function as a getter.
@@ -169,13 +206,13 @@ class FunctionAbi:
...
def encode_external_message(
- self,
- dst: Address,
- input: Dict[str, Any],
- public_key: Optional[PublicKey],
- state_init: Optional[StateInit] = None,
- timeout: Optional[int] = None,
- clock: Optional[Clock] = None
+ self,
+ dst: Address,
+ input: Dict[str, Any],
+ public_key: Optional[PublicKey] = None,
+ state_init: Optional[StateInit] = None,
+ timeout: Optional[int] = None,
+ clock: Optional[Clock] = None,
) -> UnsignedExternalMessage:
"""
Encodes external message using the function ABI.
@@ -190,12 +227,12 @@ class FunctionAbi:
...
def encode_external_input(
- self,
- input: Dict[str, Any],
- public_key: Optional[PublicKey],
- timeout: Optional[int] = None,
- address: Optional[Address] = None,
- clock: Optional[Clock] = None
+ self,
+ input: Dict[str, Any],
+ public_key: Optional[PublicKey] = None,
+ timeout: Optional[int] = None,
+ address: Optional[Address] = None,
+ clock: Optional[Clock] = None,
) -> UnsignedBody:
"""
Encodes external function input using the function ABI.
@@ -209,13 +246,13 @@ class FunctionAbi:
...
def encode_internal_message(
- self,
- input: Dict[str, Any],
- value: Tokens,
- bounce: bool,
- dst: Address,
- src: Optional[Address] = None,
- state_init: Optional[StateInit] = None,
+ self,
+ input: Dict[str, Any],
+ value: Tokens,
+ bounce: bool,
+ dst: Address,
+ src: Optional[Address] = None,
+ state_init: Optional[StateInit] = None,
) -> Message:
"""
Encodes internal message using the function ABI.
@@ -246,10 +283,7 @@ class FunctionAbi:
...
def decode_input(
- self,
- message_body: Cell,
- internal: bool,
- allow_partial: Optional[bool] = None
+ self, message_body: Cell, internal: bool, allow_partial: Optional[bool] = None
) -> Dict[str, Any]:
"""
Decodes message body as input using the function ABI.
@@ -260,7 +294,9 @@ class FunctionAbi:
"""
...
- def decode_output(self, message_body: Cell, allow_partial: Optional[bool] = None) -> Dict[str, Any]:
+ def decode_output(
+ self, message_body: Cell, allow_partial: Optional[bool] = None
+ ) -> Dict[str, Any]:
"""
Decodes message body as output using the function ABI.
@@ -270,38 +306,32 @@ class FunctionAbi:
...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
-
class FunctionAbiWithArgs:
"""Parsed function ABI."""
@property
- def abi(self) -> AbiVersion:
+ def abi(self) -> FunctionAbi:
"""Returns an underlying function ABI."""
...
@property
- def args(self) -> str:
+ def args(self) -> Dict[str, Any]:
"""Returns function input args."""
...
def call(
- self,
- account_state: AccountState,
- responsible: Optional[bool] = None,
- clock: Optional[Clock] = None,
+ self,
+ account_state: AccountState,
+ responsible: Optional[bool] = None,
+ clock: Optional[Clock] = None,
+ config: Optional[BlockchainConfig] = None,
) -> ExecutionOutput:
"""
Runs this function as a getter.
@@ -313,12 +343,12 @@ class FunctionAbiWithArgs:
...
def encode_external_message(
- self,
- dst: Address,
- public_key: Optional[PublicKey],
- state_init: Optional[StateInit] = None,
- timeout: Optional[int] = None,
- clock: Optional[Clock] = None
+ self,
+ dst: Address,
+ public_key: Optional[PublicKey] = None,
+ state_init: Optional[StateInit] = None,
+ timeout: Optional[int] = None,
+ clock: Optional[Clock] = None,
) -> UnsignedExternalMessage:
"""
Encodes external message using the function ABI.
@@ -332,11 +362,11 @@ class FunctionAbiWithArgs:
...
def encode_external_input(
- self,
- public_key: Optional[PublicKey],
- timeout: Optional[int] = None,
- address: Optional[Address] = None,
- clock: Optional[Clock] = None
+ self,
+ public_key: Optional[PublicKey] = None,
+ timeout: Optional[int] = None,
+ address: Optional[Address] = None,
+ clock: Optional[Clock] = None,
) -> UnsignedBody:
"""
Encodes external function input using the function ABI.
@@ -349,12 +379,12 @@ class FunctionAbiWithArgs:
...
def encode_internal_message(
- self,
- value: Tokens,
- bounce: bool,
- dst: Address,
- src: Optional[Address] = None,
- state_init: Optional[StateInit] = None,
+ self,
+ value: Tokens,
+ bounce: bool,
+ dst: Address,
+ src: Optional[Address] = None,
+ state_init: Optional[StateInit] = None,
) -> Message:
"""
Encodes internal message using the function ABI.
@@ -374,20 +404,13 @@ class FunctionAbiWithArgs:
...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
-
class ExecutionOutput:
@property
def exit_code(self) -> int:
@@ -399,7 +422,6 @@ class ExecutionOutput:
"""Parsed output in case of successful execution."""
...
-
class FunctionCall:
"""Parsed function call."""
@@ -413,7 +435,6 @@ class FunctionCall:
"""Parsed function output."""
...
-
class FunctionCallFull(FunctionCall):
"""Extended parsed function cell."""
@@ -427,7 +448,6 @@ class FunctionCallFull(FunctionCall):
"""ABI object of the parsed function"""
...
-
class EventAbi:
"""Parsed event ABI."""
@@ -463,19 +483,49 @@ class EventAbi:
...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
+class GetterAbi:
+ """Parsed getter ABI."""
+
+ @property
+ def name(self) -> str:
+ """Event name."""
+ ...
+
+ @property
+ def method_id(self) -> int:
+ """Method id."""
+ ...
+
+ def call(
+ self,
+ account_state: AccountState,
+ input: Dict,
+ clock: Optional[Clock] = None,
+ config: Optional[BlockchainConfig] = None,
+ ) -> ExecutionOutput:
+ """
+ Runs this function as a getter.
+
+ :param account_state: a state of existing account which will be used for execution.
+ :param input: function intput.
+ :param clock: optional clock to modify execution timestamp.
+ """
+ ...
+
+ def __eq__(self, other) -> Any: ...
+ def __ge__(self, other) -> Any: ...
+ def __gt__(self, other) -> Any: ...
+ def __hash__(self) -> Any: ...
+ def __le__(self, other) -> Any: ...
+ def __lt__(self, other) -> Any: ...
+ def __ne__(self, other) -> Any: ...
class Message:
"""
@@ -487,9 +537,7 @@ class Message:
header: MessageHeader,
body: Optional[Cell] = None,
state_init: Optional[StateInit] = None,
- ) -> None:
- ...
-
+ ) -> None: ...
@staticmethod
def from_bytes(bytes: bytes) -> Message:
"""
@@ -605,34 +653,25 @@ class Message:
...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
-
class SignedExternalMessage(Message):
"""
External message with an additional expiration param.
"""
def __init__(
- self,
- dst: Address,
- expire_at: int,
- body: Optional[Cell] = None,
- state_init: Optional[StateInit] = None
- ) -> None:
- ...
-
+ self,
+ dst: Address,
+ expire_at: int,
+ body: Optional[Cell] = None,
+ state_init: Optional[StateInit] = None,
+ ) -> None: ...
@property
def expire_at(self) -> int:
"""Expiration unix timestamp."""
@@ -642,7 +681,6 @@ class SignedExternalMessage(Message):
"""Splits into inner message and expiration timestamp."""
...
-
class UnsignedExternalMessage:
"""Unsigned external message with function intput."""
@@ -659,12 +697,14 @@ class UnsignedExternalMessage:
"""Expiration unix timestamp."""
...
- def sign(self, keypair: KeyPair, signature_id: Optional[int]) -> SignedExternalMessage:
+ def sign(
+ self, keypair: KeyPair, context: Optional[int] | SignatureContext
+ ) -> SignedExternalMessage:
"""
Signs function input with the specified keypair and signature id.
:param keypair: signer keypair.
- :param signature_id: optional signature id.
+ :param context: optional signature id or signature context.
"""
...
@@ -684,7 +724,6 @@ class UnsignedExternalMessage:
"""Creates an input without a signature."""
...
-
class UnsignedBody:
"""Unsigned function input."""
@@ -698,12 +737,12 @@ class UnsignedBody:
"""Expiration unix timestamp."""
...
- def sign(self, keypair: KeyPair, signature_id: Optional[int]) -> Cell:
+ def sign(self, keypair: KeyPair, context: Optional[int] | SignatureContext) -> Cell:
"""
Signs function input with the specified keypair and signature id.
:param keypair: signer keypair.
- :param signature_id: optional signature id.
+ :param context: optional signature id or signature context.
"""
...
@@ -723,13 +762,11 @@ class UnsignedBody:
"""Creates an input without a signature."""
...
-
class AbiParam:
"""
Base ABI type.
"""
-
class AbiUint(AbiParam):
"""
A class for `uintN` ABI type.
@@ -739,7 +776,6 @@ class AbiUint(AbiParam):
def __init__(self, size: int) -> None: ...
-
class AbiInt(AbiParam):
"""
A class for an `intN` ABI type.
@@ -749,7 +785,6 @@ class AbiInt(AbiParam):
def __init__(self, size: int) -> None: ...
-
class AbiVarUint(AbiParam):
"""
A class for `varuintN` ABI type.
@@ -759,7 +794,6 @@ class AbiVarUint(AbiParam):
def __init__(self, size: int) -> None: ...
-
class AbiVarInt(AbiParam):
"""
A class for `varintN` ABI type.
@@ -769,7 +803,6 @@ class AbiVarInt(AbiParam):
def __init__(self, size: int) -> None: ...
-
class AbiBool(AbiParam):
"""
A class for a `bool` ABI type.
@@ -777,7 +810,6 @@ class AbiBool(AbiParam):
def __init__(self) -> None: ...
-
class AbiTuple(AbiParam):
"""
A class for `(T1, T2, ..., Tn)` ABI type.
@@ -787,7 +819,6 @@ class AbiTuple(AbiParam):
def __init__(self, items: List[Tuple[str, AbiParam]]) -> None: ...
-
class AbiArray(AbiParam):
"""
A class for an `T[]` ABI type.
@@ -797,7 +828,6 @@ class AbiArray(AbiParam):
def __init__(self, value_type: AbiParam) -> None: ...
-
class AbiFixedArray(AbiParam):
"""
A class for a `T[N]` ABI type.
@@ -808,7 +838,6 @@ class AbiFixedArray(AbiParam):
def __init__(self, value_type: AbiParam, len: int) -> None: ...
-
class AbiCell(AbiParam):
"""
A class for a `cell` ABI type.
@@ -816,7 +845,6 @@ class AbiCell(AbiParam):
def __init__(self) -> None: ...
-
class AbiMap(AbiParam):
"""
A class for an `map(K, V)` ABI type.
@@ -827,7 +855,6 @@ class AbiMap(AbiParam):
def __init__(self, key_type: AbiParam, value_type: AbiParam) -> None: ...
-
class AbiAddress(AbiParam):
"""
A class for a `address` ABI type.
@@ -835,6 +862,12 @@ class AbiAddress(AbiParam):
def __init__(self) -> None: ...
+class AbiAddressStd(AbiParam):
+ """
+ A class for a `address_std` ABI type.
+ """
+
+ def __init__(self) -> None: ...
class AbiBytes(AbiParam):
"""
@@ -843,7 +876,6 @@ class AbiBytes(AbiParam):
def __init__(self) -> None: ...
-
class AbiFixedBytes(AbiParam):
"""
A class for a `fixedbytesN` ABI type.
@@ -853,7 +885,6 @@ class AbiFixedBytes(AbiParam):
def __init__(self, len: int) -> None: ...
-
class AbiString(AbiParam):
"""
A class for `string` ABI type.
@@ -861,7 +892,6 @@ class AbiString(AbiParam):
def __init__(self) -> None: ...
-
class AbiToken(AbiParam):
"""
A class for `token` ABI type.
@@ -869,7 +899,6 @@ class AbiToken(AbiParam):
def __init__(self) -> None: ...
-
class AbiOptional(AbiParam):
"""
A class for an `optional(T)` ABI type.
@@ -879,7 +908,6 @@ class AbiOptional(AbiParam):
def __init__(self, value_type: AbiParam) -> None: ...
-
class AbiRef(AbiParam):
"""
A class for a `ref(T)` ABI type.
@@ -889,7 +917,6 @@ class AbiRef(AbiParam):
def __init__(self, value_type: AbiParam) -> None: ...
-
class AbiVersion:
"""
TVM ABI version.
@@ -905,22 +932,15 @@ class AbiVersion:
"""Minor TVM ABI version component."""
def __init__(self, major: int, minor: int) -> None: ...
-
+ def __str__(self) -> str: ...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
-
#
############
@@ -928,17 +948,31 @@ class AbiVersion:
############
#
-
class BlockchainConfig:
"""
Partially parsed blockchain config.
"""
+ @property
+ def global_id(self) -> int:
+ """Network ID."""
+ ...
+
@property
def capabilities(self) -> int:
"""Required software capabilities as integer mask."""
...
+ @property
+ def signature_id(self) -> Optional[int]:
+ """Optional signature id when capability is enabled."""
+ ...
+
+ @property
+ def signature_context(self) -> SignatureContext:
+ """Network ID and capabilities that are used for signing."""
+ ...
+
@property
def global_version(self) -> int:
"""Required software version."""
@@ -988,7 +1022,6 @@ class BlockchainConfig:
"""
...
-
class AccountState:
"""
A state of an existing account.
@@ -1034,7 +1067,6 @@ class AccountState:
"""A hash of the last known state for the frozen account."""
...
-
class StorageUsed:
"""
Account storage stats.
@@ -1050,12 +1082,6 @@ class StorageUsed:
"""Number of bits occupied by this account."""
...
- @property
- def public_cells(self) -> int:
- """Number of public cells (libraries) provided by this account."""
- ...
-
-
class Transaction:
"""Blockchain transaction."""
@@ -1222,20 +1248,13 @@ class Transaction:
...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
-
class TransactionStoragePhase:
"""Transaction storage phase."""
@@ -1254,7 +1273,6 @@ class TransactionStoragePhase:
"""Account status change during this phase."""
...
-
class TransactionCreditPhase:
"""Transaction credit phase."""
@@ -1268,101 +1286,72 @@ class TransactionCreditPhase:
"""Increased balance in nano EVERs."""
...
-
class TransactionComputePhase:
"""Transaction compute phase."""
@property
def success(self) -> bool: ...
-
@property
def msg_state_used(self) -> bool: ...
-
@property
def account_activated(self) -> bool: ...
-
@property
def gas_fees(self) -> Tokens: ...
-
@property
def gas_used(self) -> int: ...
-
@property
def gas_limit(self) -> int: ...
-
@property
def gas_credit(self) -> Optional[int]: ...
-
@property
def mode(self) -> int: ...
-
@property
def exit_code(self) -> int: ...
-
@property
def exit_arg(self) -> Optional[int]: ...
-
@property
def vm_steps(self) -> int: ...
-
@property
def vm_init_state_hash(self) -> bytes: ...
-
@property
def vm_final_state_hash(self) -> bytes: ...
-
class TransactionActionPhase:
"""Transaction action phase."""
@property
def success(self) -> bool: ...
-
@property
def valid(self) -> bool: ...
-
@property
def no_funds(self) -> bool: ...
-
@property
def status_change(self) -> AccountStatusChange: ...
-
@property
def total_fwd_fees(self) -> Optional[Tokens]: ...
-
@property
def total_action_fees(self) -> Optional[Tokens]: ...
-
@property
def result_code(self) -> int: ...
-
@property
def result_arg(self) -> Optional[int]: ...
-
@property
def total_actions(self) -> int: ...
-
@property
def special_actions(self) -> int: ...
-
@property
def skipped_actions(self) -> int: ...
-
@property
def messages_created(self) -> int: ...
-
@property
def action_list_hash(self) -> bytes: ...
-
class TransactionBouncePhase:
@property
def msg_fees(self) -> Tokens: ...
-
@property
def fwd_fees(self) -> Tokens: ...
-
class TransactionType:
Ordinary: ClassVar[TransactionType] = ...
"""Ordinary transaction."""
@@ -1380,23 +1369,16 @@ class TransactionType:
"""
...
+ def __str__(self) -> str: ...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __int__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
-
class TransactionTree:
@staticmethod
def from_bytes(bytes: bytes) -> TransactionTree:
@@ -1425,7 +1407,7 @@ class TransactionTree:
...
@property
- def children(self) -> List[Transaction]:
+ def children(self) -> List[TransactionTree]:
"""
Get list of children nodes
"""
@@ -1433,17 +1415,14 @@ class TransactionTree:
def __iter__(self) -> TransactionTreeIter: ...
-
class TransactionTreeIter:
"""
Plain transaction tree iterator.
"""
def __iter__(self) -> TransactionTreeIter: ...
-
def __next__(self) -> Transaction: ...
-
class AccountStatus:
"""
Account status.
@@ -1461,23 +1440,16 @@ class AccountStatus:
Uninit: ClassVar[AccountStatus] = ...
"""Account without a state."""
+ def __str__(self) -> str: ...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __int__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
-
class AccountStatusChange:
"""
Account status change during transaction phase.
@@ -1492,31 +1464,24 @@ class AccountStatusChange:
Unchanged: ClassVar[AccountStatusChange] = ...
"""Account status has not changed."""
+ def __str__(self) -> str: ...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __int__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
-
class MessageHeader:
"""Base message header."""
+ @property
def type(self) -> MessageType:
"""Message type."""
...
-
class InternalMessageHeader(MessageHeader):
"""Internal message header."""
@@ -1532,40 +1497,28 @@ class InternalMessageHeader(MessageHeader):
fwd_fee: Optional[Tokens] = None,
created_lt: Optional[int] = None,
created_at: Optional[int] = None,
- ) -> None:
- ...
-
+ ) -> None: ...
@property
def ihr_disabled(self) -> bool: ...
-
@property
def bounce(self) -> bool: ...
-
@property
def bounced(self) -> bool: ...
-
@property
def src(self) -> Address: ...
-
@property
def dst(self) -> Address: ...
-
@property
def value(self) -> Tokens: ...
-
@property
def ihr_fee(self) -> Tokens: ...
-
@property
def fwd_fee(self) -> Tokens: ...
-
@property
def created_at(self) -> int: ...
-
@property
def created_lt(self) -> int: ...
-
class ExternalInMessageHeader(MessageHeader):
"""External incoming message header."""
@@ -1573,9 +1526,7 @@ class ExternalInMessageHeader(MessageHeader):
self,
dst: Address,
import_fee: Optional[Tokens] = None,
- ) -> None:
- ...
-
+ ) -> None: ...
@property
def dst(self) -> Address:
"""Message destination."""
@@ -1586,18 +1537,15 @@ class ExternalInMessageHeader(MessageHeader):
"""Import fee in nano EVERs"""
...
-
class ExternalOutMessageHeader(MessageHeader):
"""External outgoing message header."""
def __init__(
self,
- src: Optional[Address],
+ src: Optional[Address] = None,
created_lt: Optional[int] = None,
created_at: Optional[int] = None,
- ) -> None:
- ...
-
+ ) -> None: ...
@property
def src(self) -> Address:
"""Message source."""
@@ -1613,7 +1561,6 @@ class ExternalOutMessageHeader(MessageHeader):
"""A logical time when the message was created."""
...
-
class MessageType:
"""Message type."""
@@ -1626,23 +1573,16 @@ class MessageType:
ExternalOut: ClassVar[MessageType] = ...
"""External outgoing message. (Events)."""
+ def __str__(self) -> str: ...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __int__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
-
class StateInit:
"""
Contract code and data.
@@ -1685,14 +1625,15 @@ class StateInit:
"""
...
- def __init__(self, code: Optional[Cell], data: Optional[Cell]) -> None: ...
-
+ def __init__(
+ self, code: Optional[Cell] = None, data: Optional[Cell] = None
+ ) -> None: ...
@property
def code_hash(self) -> Optional[bytes]:
"""Optional code hash."""
...
- def set_code_salt(self, salt: Cell):
+ def set_code_salt(self, salt: Cell) -> None:
"""
Tries to update the code salt.
@@ -1730,7 +1671,6 @@ class StateInit:
"""Creates a new cell with StateInit."""
...
-
class Address:
"""
Account address (`StdAddr`).
@@ -1751,7 +1691,7 @@ class Address:
...
@staticmethod
- def from_parts(workchain: int, account: bytes) -> Any:
+ def from_parts(workchain: int, account: bytes) -> "Address":
"""
Creates an address from parts.
@@ -1761,39 +1701,49 @@ class Address:
...
def __init__(self, addr: str) -> None: ...
-
@property
def account(self) -> bytes:
"""Hash of the initial state."""
...
- def to_base64(self, url_safe: bool = True, bounce: bool = False):
+ def to_base64(self, url_safe: bool = True, bounce: bool = False) -> str:
"""
Encodes address to a base64 format.
"""
...
- def __str__(self):
+ def as_cell(self) -> Cell:
+ """
+ Builds a cell with stored address.
+ """
+ ...
+
+ def as_slice(self) -> CellSlice:
+ """
+ Builds a cell slice with stored address.
+ """
+ ...
+
+ def as_builder(self) -> CellBuilder:
+ """
+ Creates a new cell builder and stores this address in it.
+ """
+ ...
+
+ def __str__(self) -> str:
"""
Encodes address to a raw format.
"""
...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
-
class CellSlice:
"""
A read-only view for a subrange of a cell.
@@ -1824,6 +1774,18 @@ class CellSlice:
"""Returns the start of the references window."""
...
+ def advance(self, bits=None, refs=None) -> None:
+ """
+ Skips a slice prefix.
+ """
+ ...
+
+ def shrink(self, bits=None, refs=None) -> None:
+ """
+ Removes all but the specified prefix.
+ """
+ ...
+
def is_empty(self) -> bool:
"""Returns whether there are no bits and refs left."""
...
@@ -1968,17 +1930,15 @@ class CellSlice:
"""Tries to read the next cell, incrementing the refs window start."""
...
-
class CellBuilder:
"""
Builder for constructing cells with densely packed data.
"""
- is_exotic: Optional[Cell]
+ is_exotic: bool
"""Whether this cell will be built as an exotic."""
def __init__(self) -> None: ...
-
@property
def bits(self) -> int:
"""Data length in bits."""
@@ -2003,111 +1963,111 @@ class CellBuilder:
"""Tries to build a new cell from the builder."""
...
- def store_zeros(self, bits: int):
+ def store_zeros(self, bits: int) -> None:
"""Tries to store the specified number of zero bits into the cell."""
...
- def store_ones(self, bits: int):
+ def store_ones(self, bits: int) -> None:
"""Tries to store the specified number of set bits into the cell."""
...
- def store_bit_zero(self):
+ def store_bit_zero(self) -> None:
"""Tries to store one zero bit into the cell."""
...
- def store_bit_one(self):
+ def store_bit_one(self) -> None:
"""Tries to store one non-zero bit into the cell."""
...
- def store_bit(self, value: bool):
+ def store_bit(self, value: bool) -> None:
"""Tries to store one bit into the cell."""
...
- def store_u8(self, value: int):
+ def store_u8(self, value: int) -> None:
"""Tries to store u8 into the cell."""
...
- def store_i8(self, value: int):
+ def store_i8(self, value: int) -> None:
"""Tries to store i8 into the cell."""
...
- def store_u16(self, value: int):
+ def store_u16(self, value: int) -> None:
"""Tries to store u16 into the cell."""
...
- def store_i16(self, value: int):
+ def store_i16(self, value: int) -> None:
"""Tries to store i16 into the cell."""
...
- def store_u32(self, value: int):
+ def store_u32(self, value: int) -> None:
"""Tries to store u32 into the cell."""
...
- def store_i32(self, value: int):
+ def store_i32(self, value: int) -> None:
"""Tries to store i32 into the cell."""
...
- def store_u64(self, value: int):
+ def store_u64(self, value: int) -> None:
"""Tries to store u64 into the cell."""
...
- def store_i64(self, value: int):
+ def store_i64(self, value: int) -> None:
"""Tries to store i64 into the cell."""
...
- def store_u128(self, value: int):
+ def store_u128(self, value: int) -> None:
"""Tries to store u128 into the cell."""
...
- def store_i128(self, value: int):
+ def store_i128(self, value: int) -> None:
"""Tries to store i128 into the cell."""
...
- def store_uint(self, value: int, bits: int):
+ def store_uint(self, value: int, bits: int) -> None:
"""Tries to store an unsigned integer into the cell."""
...
- def store_int(self, value: int, bits: int):
+ def store_int(self, value: int, bits: int) -> None:
"""Tries to store a signed integer into the cell."""
...
- def store_public_key(self, public_key: PublicKey):
+ def store_public_key(self, value: PublicKey) -> None:
"""Tries to store a public key into the cell."""
...
- def store_signature(self, signature: Signature):
+ def store_signature(self, signature: Signature) -> None:
"""Tries to store a signature into the cell."""
...
- def store_bytes(self, bytes: bytes):
+ def store_bytes(self, bytes: bytes) -> None:
"""Tries to store bytes into the cell."""
...
- def store_raw(self, bytes: bytes, bits: int):
+ def store_raw(self, bytes: bytes, bits: int) -> None:
"""Tries to store a raw data into the cell."""
...
- def store_reference(self, cell: Cell):
+ def store_reference(self, cell: Cell) -> None:
"""Tries to store a child into the cell."""
...
- def store_builder(self, builder: CellBuilder):
+ def store_builder(self, value: CellBuilder) -> None:
"""Tries to append a builder."""
...
- def store_slice(self, slice: CellSlice):
+ def store_slice(self, value: CellSlice) -> None:
"""Tries to append a cell slice."""
...
def store_abi(
+ self,
abi: List[Tuple[str, AbiParam]],
value: Dict[str, Any],
abi_version: Optional[AbiVersion] = None,
- ):
+ ) -> None:
"""Tries to store an abi encoded value into the cell."""
...
-
class Cell:
"""
A container with up to 1023 bits of data and up to 4 children.
@@ -2124,9 +2084,9 @@ class Cell:
@staticmethod
def build(
- abi: List[Tuple[str, AbiParam]],
- value: Dict[str, Any],
- abi_version: Optional[AbiVersion] = None,
+ abi: List[Tuple[str, AbiParam]],
+ value: Dict[str, Any],
+ abi_version: Optional[AbiVersion] = None,
) -> Cell:
"""
Packs values into cell using the provided ABI.
@@ -2148,7 +2108,6 @@ class Cell:
...
def __init__(self) -> None: ...
-
@property
def repr_hash(self) -> bytes:
"""Representation hash of the cell."""
@@ -2181,10 +2140,10 @@ class Cell:
...
def unpack(
- self,
- abi: List[Tuple[str, AbiParam]],
- abi_version: Optional[AbiVersion] = None,
- allow_partial: Optional[bool] = None,
+ self,
+ abi: List[Tuple[str, AbiParam]],
+ abi_version: Optional[AbiVersion] = None,
+ allow_partial: Optional[bool] = None,
) -> Dict[str, Any]:
"""
Unpack values using the provided ABI.
@@ -2209,20 +2168,13 @@ class Cell:
...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
-
class Tokens:
"""
Wrapper around native currency.
@@ -2233,7 +2185,7 @@ class Tokens:
"""Wraps amount in nano."""
...
- def __init__(self, value: str | int):
+ def __init__(self, value: str | int) -> None:
"""Constructs tokens from decimal or integer value."""
...
@@ -2260,42 +2212,25 @@ class Tokens:
...
def abs(self) -> Tokens: ...
-
+ def __str__(self) -> str: ...
def __bool__(self) -> bool: ...
-
def __int__(self) -> int: ...
-
def __add__(self, other: Tokens) -> Tokens: ...
-
def __sub__(self, other: Tokens) -> Tokens: ...
-
def __mul__(self, other: int) -> Tokens: ...
-
def __rmul__(self, other: int) -> Tokens: ...
-
def __truediv__(self, other: int) -> Tokens: ...
-
def __pos__(self) -> Tokens: ...
-
def __neg__(self) -> Tokens: ...
-
def __abs__(self) -> Tokens: ...
-
def __eq__(self, other: Tokens) -> Any: ...
-
def __ge__(self, other: Tokens) -> Any: ...
-
def __gt__(self, other: Tokens) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __le__(self, other: Tokens) -> Any: ...
-
def __lt__(self, other: Tokens) -> Any: ...
-
def __ne__(self, other: Tokens) -> Any: ...
-
#
###############
@@ -2303,7 +2238,6 @@ class Tokens:
###############
#
-
class Transport:
"""Base transport"""
@@ -2312,11 +2246,13 @@ class Transport:
"""Time context."""
...
- async def check_connection(self):
+ async def check_connection(self) -> None:
"""Checks the connection."""
...
- async def send_external_message(self, message: SignedExternalMessage) -> Optional[Transaction]:
+ async def send_external_message(
+ self, message: SignedExternalMessage
+ ) -> Optional[Transaction]:
"""
Sends an external message to the network and waits until the transaction.
@@ -2328,7 +2264,13 @@ class Transport:
"""Fetches signature id for the selected network."""
...
- async def get_blockchain_config(self, force: Optional[bool] = None) -> BlockchainConfig:
+ async def get_signature_context(self) -> SignatureContext:
+ """Fetches signature context from the selected network."""
+ ...
+
+ async def get_blockchain_config(
+ self, force: Optional[bool] = None
+ ) -> BlockchainConfig:
"""
Fetches the latest blockchain config.
@@ -2345,10 +2287,10 @@ class Transport:
...
async def get_accounts_by_code_hash(
- self,
- code_hash: bytes,
- continuation: Optional[Address] = None,
- limit: Optional[int] = None,
+ self,
+ code_hash: bytes,
+ continuation: Optional[Address] = None,
+ limit: Optional[int] = None,
) -> List[Address]:
"""
Fetches a list of address of accounts with the specified code hash.
@@ -2367,7 +2309,9 @@ class Transport:
"""
...
- async def get_dst_transaction(self, message_hash: bytes | Message) -> Optional[Transaction]:
+ async def get_dst_transaction(
+ self, message_hash: bytes | Message
+ ) -> Optional[Transaction]:
"""
Searches for a transaction by the hash of incoming message.
@@ -2376,10 +2320,10 @@ class Transport:
...
async def get_transactions(
- self,
- address: Address,
- lt: Optional[int] = None,
- limit: Optional[int] = None,
+ self,
+ address: Address,
+ lt: Optional[int] = None,
+ limit: Optional[int] = None,
) -> List[Transaction]:
"""
Fetches a transactions batch for the specified account.
@@ -2406,7 +2350,9 @@ class Transport:
"""
...
- def trace_transaction(self, transaction_hash: bytes | Transaction, yield_root: bool = False) -> TraceTransaction:
+ def trace_transaction(
+ self, transaction_hash: bytes | Transaction, yield_root: bool = False
+ ) -> TraceTransaction:
"""
Returns an async transactions iterator over the transactions tree.
@@ -2415,7 +2361,6 @@ class Transport:
"""
...
-
class GqlTransport(Transport):
"""
GraphQl transport.
@@ -2426,17 +2371,16 @@ class GqlTransport(Transport):
"""
def __init__(
- self,
- endpoints: List[str],
- clock: Optional[Clock] = None,
- local: Optional[bool] = None,
+ self,
+ endpoints: List[str],
+ clock: Optional[Clock] = None,
+ local: Optional[bool] = None,
) -> None: ...
-
async def query_transactions(
- self,
- filter: str | GqlExprPart | List[GqlExprPart],
- order_by: Optional[str | GqlExprPart | List[GqlExprPart]] = None,
- limit: Optional[int] = None
+ self,
+ filter: str | GqlExprPart | List[GqlExprPart],
+ order_by: Optional[str | GqlExprPart | List[GqlExprPart]] = None,
+ limit: Optional[int] = None,
) -> List[Transaction]:
"""
Transactions GQL query.
@@ -2448,11 +2392,11 @@ class GqlTransport(Transport):
...
async def query_messages(
- self,
- filter: str | GqlExprPart | List[GqlExprPart],
- order_by: Optional[str | GqlExprPart | List[GqlExprPart]] = None,
- limit: Optional[int] = None
- ) -> List[Transaction]:
+ self,
+ filter: str | GqlExprPart | List[GqlExprPart],
+ order_by: Optional[str | GqlExprPart | List[GqlExprPart]] = None,
+ limit: Optional[int] = None,
+ ) -> List[Message]:
"""
Messages GQL query.
@@ -2463,10 +2407,10 @@ class GqlTransport(Transport):
...
async def query_accounts(
- self,
- filter: str | GqlExprPart | List[GqlExprPart],
- order_by: Optional[str | GqlExprPart | List[GqlExprPart]] = None,
- limit: Optional[int] = None
+ self,
+ filter: str | GqlExprPart | List[GqlExprPart],
+ order_by: Optional[str | GqlExprPart | List[GqlExprPart]] = None,
+ limit: Optional[int] = None,
) -> List[Tuple[Address, Optional[AccountState]]]:
"""
Accounts GQL query.
@@ -2477,7 +2421,6 @@ class GqlTransport(Transport):
"""
...
-
class GqlExprPart:
"""
GQL query part.
@@ -2485,10 +2428,8 @@ class GqlExprPart:
:param value: part value.
"""
- def __init__(self, value: str): ...
-
- def __str__(self): ...
-
+ def __init__(self, value: str) -> None: ...
+ def __str__(self) -> str: ...
class JrpcTransport(Transport):
"""
@@ -2498,9 +2439,7 @@ class JrpcTransport(Transport):
:param clock: optional clock to modify timestamp.
"""
- def __init__(self, endpoint: str,
- clock: Optional[Clock] = None) -> None: ...
-
+ def __init__(self, endpoint: str, clock: Optional[Clock] = None) -> None: ...
class ProtoTransport(Transport):
"""
@@ -2510,75 +2449,61 @@ class ProtoTransport(Transport):
:param clock: optional clock to modify timestamp.
"""
- def __init__(self, endpoint: str,
- clock: Optional[Clock] = None) -> None: ...
-
+ def __init__(self, endpoint: str, clock: Optional[Clock] = None) -> None: ...
class AccountStatesAsyncIter:
"""
Async account states iterator.
"""
- async def close(self):
+ async def close(self) -> None:
"""
Closes async iterator.
"""
...
async def __aenter__(self) -> AccountStatesAsyncIter: ...
-
- async def __aexit__(self, exc_type, exc_val, exc_tb): ...
-
+ async def __aexit__(self, exc_type, exc_val, exc_tb) -> None: ...
def __aiter__(self) -> AccountStatesAsyncIter: ...
-
- def __anext__(self) -> Optional[AccountState]: ...
-
+ async def __anext__(self) -> Optional[AccountState]: ...
class AccountTransactionsAsyncIter:
"""
Async account transactions iterator.
"""
- async def close(self):
+ async def close(self) -> None:
"""
Closes async iterator.
"""
...
async def __aenter__(self) -> AccountTransactionsAsyncIter: ...
-
- async def __aexit__(self, exc_type, exc_val, exc_tb): ...
-
+ async def __aexit__(self, exc_type, exc_val, exc_tb) -> None: ...
def __aiter__(self) -> AccountTransactionsAsyncIter: ...
-
- def __anext__(self) -> Tuple[List[Transaction], TransactionsBatchInfo]: ...
-
+ async def __anext__(self) -> Tuple[List[Transaction], TransactionsBatchInfo]: ...
class TraceTransaction:
"""
Async transactions tree iterator.
"""
- async def close(self):
+ async def close(self) -> None:
"""
Closes async iterator.
"""
...
- async def wait(self):
+ async def wait(self) -> None:
"""
Waits for the last transaction.
"""
...
async def __aenter__(self) -> TraceTransaction: ...
-
- async def __aexit__(self, exc_type, exc_val, exc_tb): ...
-
+ async def __aexit__(self, exc_type, exc_val, exc_tb) -> None: ...
def __aiter__(self) -> TraceTransaction: ...
-
- def __anext__(self) -> Transaction: ...
-
+ async def __anext__(self) -> Transaction: ...
class TransactionsBatchInfo:
"""
@@ -2595,7 +2520,6 @@ class TransactionsBatchInfo:
"""The highest logical time in batch."""
...
-
class Clock:
"""
Time context.
@@ -2607,7 +2531,6 @@ class Clock:
"""Clock offset in milliseconds."""
def __init__(self, offset: Optional[int] = None) -> None: ...
-
@property
def now_sec(self) -> int:
"""Returns current timestamp in seconds."""
@@ -2618,7 +2541,6 @@ class Clock:
"""Returns current timestamp in milliseconds."""
...
-
#
############
@@ -2626,6 +2548,32 @@ class Clock:
############
#
+class SignatureContext:
+ """
+ Signature Context.
+
+ :param global_id: a network ID.
+ :param capabilities: raw network capabilities.
+ """
+
+ def __init__(self, global_id: int, capabilities: int) -> None: ...
+ @property
+ def global_id(self) -> int:
+ """Network ID."""
+ ...
+
+ @property
+ def capabilities(self) -> int:
+ """Raw network capabilities."""
+ ...
+
+ def apply(self, data: bytes) -> bytes:
+ """
+ Applies signature context prefix to data.
+
+ :param data: data to sign.
+ """
+ ...
class PublicKey:
"""
@@ -2654,14 +2602,18 @@ class PublicKey:
...
def __init__(self, value: str, encoding: Optional[str] = None) -> None: ...
-
- def check_signature(self, data: bytes, signature: Signature, signature_id: Optional[int] = None) -> bool:
+ def check_signature(
+ self,
+ data: bytes,
+ signature: Signature,
+ context: Optional[int] | SignatureContext,
+ ) -> bool:
"""
Returns `True` if the signature is correct.
:param data: signed message.
:param signature: signature to check.
- :param signature_id: optional signature id.
+ :param context: optional signature id or signature context.
"""
...
@@ -2681,21 +2633,15 @@ class PublicKey:
"""Converts public key into integer."""
...
+ def __str__(self) -> str: ...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
-
class KeyPair:
"""
Ed25519 key pair.
@@ -2709,7 +2655,6 @@ class KeyPair:
...
def __init__(self, secret: bytes) -> None: ...
-
@property
def secret_key(self) -> bytes:
"""Corresponding secret key."""
@@ -2720,49 +2665,49 @@ class KeyPair:
"""Corresponding public key."""
...
- def sign(self, data: bytes, signature_id: Optional[int]) -> Signature:
+ def sign(self, data: bytes, context: Optional[int] | SignatureContext) -> Signature:
"""
Signs a hash of the specified data.
:param data: data to sign.
- :param signature_id: optional signature id.
+ :param context: optional signature id or context.
"""
...
- def sign_raw(self, data: bytes, signature_id: Optional[int]) -> Signature:
+ def sign_raw(
+ self, data: bytes, context: Optional[int] | SignatureContext
+ ) -> Signature:
"""
Signs data as is.
:param data: data to sign.
- :param signature_id: optional signature id.
+ :param context: optional signature id or context.
"""
...
- def check_signature(self, data: bytes, signature: Signature, signature_id: Optional[int] = None) -> bool:
+ def check_signature(
+ self,
+ data: bytes,
+ signature: Signature,
+ context: Optional[int] | SignatureContext,
+ ) -> bool:
"""
Returns `True` if the signature is correct.
:param data: signed message.
:param signature: signature to check.
- :param signature_id: optional signature id.
+ :param context: optional signature id or signature context.
"""
...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
-
class Signature:
"""
Ed25519 signature.
@@ -2781,7 +2726,6 @@ class Signature:
...
def __init__(self, value: str, encoding: Optional[str] = None) -> None: ...
-
def encode(self, encoding: Optional[str] = None) -> str:
"""
Encodes signature into string.
@@ -2795,20 +2739,13 @@ class Signature:
...
def __eq__(self, other) -> Any: ...
-
def __ge__(self, other) -> Any: ...
-
def __gt__(self, other) -> Any: ...
-
def __hash__(self) -> Any: ...
-
def __le__(self, other) -> Any: ...
-
def __lt__(self, other) -> Any: ...
-
def __ne__(self, other) -> Any: ...
-
class Seed:
"""Base seed."""
@@ -2817,6 +2754,7 @@ class Seed:
"""Number of words in phrase."""
...
+ def __str__(self) -> str: ...
class LegacySeed(Seed):
"""
@@ -2831,12 +2769,10 @@ class LegacySeed(Seed):
...
def __init__(self, phrase: str) -> None: ...
-
def derive(self) -> KeyPair:
"""Derives a key pair."""
...
-
class Bip39Seed(Seed):
"""
BIP39 seed.
@@ -2859,7 +2795,6 @@ class Bip39Seed(Seed):
...
def __init__(self, phrase: str) -> None: ...
-
def derive(self, path: Optional[str] = None) -> KeyPair:
"""
Derives a key pair using some derivation path.
@@ -2870,7 +2805,6 @@ class Bip39Seed(Seed):
#
-
#########
## ASM ##
#########
diff --git a/src/abi.rs b/src/abi.rs
index 83e4192..ac91be2 100644
--- a/src/abi.rs
+++ b/src/abi.rs
@@ -3,11 +3,13 @@ use std::path::PathBuf;
use std::sync::atomic::AtomicU64;
use std::sync::Arc;
+use nt::abi::AsGetterMethodId;
+use num_traits::Zero;
use pyo3::exceptions::*;
use pyo3::prelude::*;
use pyo3::types::*;
use rand::Rng;
-use ton_block::{GetRepresentationHash, Serializable};
+use ton_block::{Deserializable, GetRepresentationHash, Serializable};
use crate::crypto::{KeyPair, PublicKey, Signature};
use crate::models::*;
@@ -130,7 +132,8 @@ impl ContractAbi {
#[new]
fn new(abi: &str) -> PyResult {
- let contract = ton_abi::Contract::load(abi.trim()).handle_value_error()?;
+ let contract =
+ ton_abi::Contract::load(std::io::Cursor::new(abi.trim())).handle_value_error()?;
let functions = contract
.functions
@@ -144,10 +147,17 @@ impl ContractAbi {
.map(|(name, abi)| (name.clone(), EventAbi(Arc::new(abi.clone()))))
.collect();
+ let getters = contract
+ .getters
+ .iter()
+ .map(|(name, abi)| (name.clone(), GetterAbi(Arc::new(abi.clone()))))
+ .collect();
+
let shared = Arc::new(SharedContractAbi {
contract,
functions,
events,
+ getters,
});
Ok(Self(shared))
@@ -162,55 +172,48 @@ impl ContractAbi {
self.0.functions.get(name).cloned()
}
+ fn function(&self, name: &str) -> PyResult {
+ match self.0.functions.get(name).cloned() {
+ Some(function) => Ok(function),
+ None => Err(PyKeyError::new_err(format!("Function not found: {name}"))),
+ }
+ }
+
fn get_event(&self, name: &str) -> Option {
self.0.events.get(name).cloned()
}
+ fn event(&self, name: &str) -> PyResult {
+ match self.0.events.get(name).cloned() {
+ Some(event) => Ok(event),
+ None => Err(PyKeyError::new_err(format!("Event not found: {name}"))),
+ }
+ }
+
+ fn get_getter(&self, name: &str) -> Option {
+ self.0.getters.get(name).cloned()
+ }
+
+ fn getter(&self, name: &str) -> PyResult {
+ match self.0.getters.get(name).cloned() {
+ Some(getter) => Ok(getter),
+ None => Err(PyKeyError::new_err(format!("Getter not found: {name}"))),
+ }
+ }
+
fn encode_init_data(
&self,
data: &PyDict,
public_key: Option<&PublicKey>,
existing_data: Option,
) -> PyResult {
- let mut map = ton_types::HashmapE::with_hashmap(
- ton_abi::Contract::DATA_MAP_KEYLEN,
- existing_data.and_then(|Cell(cell)| cell.reference(0).ok()),
- );
-
- if let Some(public_key) = public_key {
- map.set_builder(
- serialize_state_init_data_key(0),
- ton_types::BuilderData::new()
- .append_raw(public_key.0.as_bytes(), 256)
- .unwrap(),
- )
- .handle_runtime_error()?;
- }
-
- if !self.0.contract.data.is_empty() {
- for (param_name, param) in &self.0.contract.data {
- let value = match data.get_item(param_name) {
- Some(value) => parse_token(¶m.value.kind, value)?,
- None => {
- return Err(PyValueError::new_err(format!(
- "Param '{param_name}' not found"
- )))
- }
- };
-
- let builder = value
- .pack_into_chain(&self.0.contract.abi_version)
- .handle_runtime_error()?;
-
- map.set_builder(serialize_state_init_data_key(param.key), &builder)
- .handle_runtime_error()?;
- }
+ if self.0.contract.abi_version < ton_abi::contract::ABI_VERSION_2_4 {
+ encode_init_data_dict(&self.0.contract, data, public_key, existing_data)
+ } else if let Some(existing_data) = existing_data {
+ update_init_data_plain(&self.0.contract, data, public_key, existing_data)
+ } else {
+ encode_init_data_plain(&self.0.contract, data, public_key)
}
-
- map.write_to_new_cell()
- .and_then(ton_types::BuilderData::into_cell)
- .handle_runtime_error()
- .map(Cell)
}
fn decode_init_data<'a>(
@@ -218,35 +221,11 @@ impl ContractAbi {
py: Python<'a>,
data: &Cell,
) -> PyResult<(Option, &'a PyDict)> {
- let pubkey = {
- let map = ton_types::HashmapE::with_hashmap(
- ton_abi::Contract::DATA_MAP_KEYLEN,
- data.0.reference(0).ok(),
- );
-
- let value = map
- .get(serialize_state_init_data_key(0))
- .handle_value_error()?;
- match value {
- Some(mut value) => {
- let pubkey = value.get_next_hash().handle_value_error()?;
- if pubkey.is_zero() {
- None
- } else {
- Some(PublicKey(
- ed25519_dalek::PublicKey::from_bytes(pubkey.as_slice())
- .handle_value_error()?,
- ))
- }
- }
- None => None,
- }
- };
-
- let data = ton_types::SliceData::load_cell_ref(&data.0).handle_value_error()?;
-
- let tokens = self.0.contract.decode_data(data).handle_value_error()?;
- Ok((pubkey, convert_tokens(py, tokens)?))
+ if self.0.contract.abi_version < ton_abi::contract::ABI_VERSION_2_4 {
+ decode_init_data_dict(py, &self.0.contract, data)
+ } else {
+ decode_init_data_plain(py, &self.0.contract, data)
+ }
}
fn decode_fields<'a>(
@@ -314,7 +293,7 @@ impl ContractAbi {
let input = function
.0
- .decode_input(in_msg_body, in_msg.is_internal())
+ .decode_input(in_msg_body, in_msg.is_internal(), false)
.handle_runtime_error()?;
let mut output = None;
@@ -414,10 +393,222 @@ impl ContractAbi {
}
}
+fn encode_init_data_dict(
+ contract: &ton_abi::Contract,
+ data: &PyDict,
+ public_key: Option<&PublicKey>,
+ existing_data: Option,
+) -> PyResult {
+ let mut map = ton_types::HashmapE::with_hashmap(
+ ton_abi::Contract::DATA_MAP_KEYLEN,
+ existing_data.and_then(|Cell(cell)| cell.reference(0).ok()),
+ );
+
+ if let Some(public_key) = public_key {
+ map.set_builder(
+ serialize_state_init_data_key(0),
+ ton_types::BuilderData::new()
+ .append_raw(public_key.0.as_bytes(), 256)
+ .unwrap(),
+ )
+ .handle_runtime_error()?;
+ }
+
+ if !contract.data.is_empty() {
+ for (param_name, param) in &contract.data {
+ let value = match data.get_item(param_name) {
+ Some(value) => parse_token(¶m.value.kind, value)?,
+ None => {
+ return Err(PyValueError::new_err(format!(
+ "Param '{param_name}' not found"
+ )))
+ }
+ };
+
+ let builder = value
+ .pack_into_chain(&contract.abi_version)
+ .handle_runtime_error()?;
+
+ map.set_builder(serialize_state_init_data_key(param.key), &builder)
+ .handle_runtime_error()?;
+ }
+ }
+
+ map.write_to_new_cell()
+ .and_then(ton_types::BuilderData::into_cell)
+ .handle_runtime_error()
+ .map(Cell)
+}
+
+fn decode_init_data_dict<'a>(
+ py: Python<'a>,
+ contract: &ton_abi::Contract,
+ data: &Cell,
+) -> PyResult<(Option, &'a PyDict)> {
+ let pubkey = {
+ let map = ton_types::HashmapE::with_hashmap(
+ ton_abi::Contract::DATA_MAP_KEYLEN,
+ data.0.reference(0).ok(),
+ );
+
+ let value = map
+ .get(serialize_state_init_data_key(0))
+ .handle_value_error()?;
+ match value {
+ Some(mut value) => {
+ let pubkey = value.get_next_hash().handle_value_error()?;
+ if pubkey.is_zero() {
+ None
+ } else {
+ Some(PublicKey(
+ ed25519_dalek::PublicKey::from_bytes(pubkey.as_slice())
+ .handle_value_error()?,
+ ))
+ }
+ }
+ None => None,
+ }
+ };
+
+ let data = ton_types::SliceData::load_cell_ref(&data.0).handle_value_error()?;
+
+ let tokens = contract.decode_init_data(data).handle_value_error()?;
+ Ok((pubkey, convert_tokens(py, tokens)?))
+}
+
+fn update_init_data_plain(
+ contract: &ton_abi::Contract,
+ data: &PyDict,
+ mut public_key: Option<&PublicKey>,
+ existing_data: Cell,
+) -> PyResult {
+ let data_slice = ton_types::SliceData::load_cell(existing_data.0).handle_value_error()?;
+ let old_values = ton_abi::TokenValue::decode_params(
+ &contract.fields,
+ data_slice,
+ &contract.abi_version,
+ false,
+ )
+ .handle_value_error()?;
+
+ let mut result = Vec::with_capacity(old_values.len());
+ for (field, old_value) in std::iter::zip(&contract.fields, old_values) {
+ let mut token = match data.get_item(&field.name) {
+ Some(value) => Some(parse_token(&field.kind, value)?),
+ None => None,
+ };
+
+ if field.name == PUBKEY_FIELD {
+ if let Some(pubkey) = public_key.take() {
+ // Overwrite pubkey if specified.
+ token = Some(ton_abi::TokenValue::Uint(ton_abi::Uint {
+ size: 256,
+ number: num_bigint::BigUint::from_bytes_be(pubkey.0.as_bytes()),
+ }));
+ }
+ }
+
+ result.push(if let Some(token) = token {
+ if !contract.init_fields.contains(&field.name) {
+ return Err(PyValueError::new_err(format!(
+ "Unexpected '{}' init data param",
+ field.name
+ )));
+ }
+
+ ton_abi::Token::new(&field.name, token)
+ } else {
+ old_value
+ });
+ }
+
+ if public_key.is_some() {
+ return Err(PyValueError::new_err("Explicit pubkey was not used"));
+ }
+
+ ton_abi::TokenValue::pack_values_into_chain(&result, Vec::new(), &contract.abi_version)
+ .and_then(ton_types::BuilderData::into_cell)
+ .map(Cell)
+ .handle_runtime_error()
+}
+
+fn encode_init_data_plain(
+ contract: &ton_abi::Contract,
+ data: &PyDict,
+ mut public_key: Option<&PublicKey>,
+) -> PyResult {
+ let mut init_fields = HashMap::default();
+ for field in &contract.fields {
+ if let Some(value) = data.get_item(&field.name) {
+ init_fields.insert(field.name.clone(), parse_token(&field.kind, value)?);
+ }
+ }
+
+ if contract.init_fields.contains(PUBKEY_FIELD) {
+ if let Some(pubkey) = public_key.take() {
+ // Overwrite pubkey if specified.
+ init_fields.insert(
+ PUBKEY_FIELD.to_owned(),
+ ton_abi::TokenValue::Uint(ton_abi::Uint {
+ size: 256,
+ number: num_bigint::BigUint::from_bytes_be(pubkey.0.as_bytes()),
+ }),
+ );
+ }
+ }
+
+ if public_key.is_some() {
+ return Err(PyValueError::new_err("Explicit pubkey was not used"));
+ }
+
+ contract
+ .encode_storage_fields(init_fields)
+ .and_then(ton_types::BuilderData::into_cell)
+ .map(Cell)
+ .handle_runtime_error()
+}
+
+fn decode_init_data_plain<'a>(
+ py: Python<'a>,
+ contract: &ton_abi::Contract,
+ data: &Cell,
+) -> PyResult<(Option, &'a PyDict)> {
+ use nt::abi::UnpackAbi;
+
+ let data_slice = ton_types::SliceData::load_cell(data.0.clone()).handle_value_error()?;
+ let mut values = ton_abi::TokenValue::decode_params(
+ &contract.fields,
+ data_slice,
+ &contract.abi_version,
+ false,
+ )
+ .handle_value_error()?;
+
+ values.retain(|item| contract.init_fields.contains(&item.name));
+
+ let pubkey = 'pubkey: {
+ if let Some(pubkey) = values.iter().find(|item| item.name == PUBKEY_FIELD) {
+ let value: ton_types::UInt256 = pubkey.clone().unpack().handle_value_error()?;
+ if !value.is_zero() {
+ break 'pubkey Some(PublicKey(
+ ed25519_dalek::PublicKey::from_bytes(value.as_slice()).handle_value_error()?,
+ ));
+ }
+ }
+
+ None
+ };
+
+ Ok((pubkey, convert_tokens(py, values)?))
+}
+
+const PUBKEY_FIELD: &str = "_pubkey";
+
struct SharedContractAbi {
contract: ton_abi::Contract,
functions: FastHashMap,
events: FastHashMap,
+ getters: FastHashMap,
}
#[derive(FromPyObject)]
@@ -454,10 +645,10 @@ impl FunctionAbi {
self.0.output_id
}
- fn with_args(&self, py: Python<'_>, args: &PyDict) -> FunctionAbiWithArgs {
+ fn with_args(&self, py: Python<'_>, input: &PyDict) -> FunctionAbiWithArgs {
FunctionAbiWithArgs {
abi: self.clone(),
- args: args.into_py(py),
+ args: input.into_py(py),
}
}
@@ -486,7 +677,14 @@ impl FunctionAbi {
let responsible = matches!(responsible, Some(true));
let execution_output = self
.0
- .run_local_ext(clock, account_state.0.clone(), &input, responsible, &config)
+ .run_local_ext(
+ clock,
+ account_state.0.clone(),
+ &input,
+ responsible,
+ &config,
+ &[],
+ )
.handle_runtime_error()?;
Ok(ExecutionOutput {
@@ -625,7 +823,7 @@ impl FunctionAbi {
let input = self
.0
- .decode_input(in_msg_body, in_msg.is_internal())
+ .decode_input(in_msg_body, in_msg.is_internal(), false)
.handle_runtime_error()?;
let output = self.0.parse(tx).handle_runtime_error()?;
@@ -644,12 +842,9 @@ impl FunctionAbi {
) -> PyResult<&'a PyDict> {
let abi = self.0.as_ref();
let body = ton_types::SliceData::load_cell_ref(&message_body.0).handle_value_error()?;
- let values = if matches!(allow_partial, Some(true)) {
- abi.decode_input_partial(body, internal)
- } else {
- abi.decode_input(body, internal)
- }
- .handle_runtime_error()?;
+ let values = abi
+ .decode_input(body, internal, matches!(allow_partial, Some(true)))
+ .handle_runtime_error()?;
convert_tokens(py, values)
}
@@ -906,6 +1101,107 @@ impl EventAbi {
}
}
+#[derive(Clone)]
+#[pyclass(subclass)]
+pub struct GetterAbi(Arc);
+
+#[pymethods]
+impl GetterAbi {
+ #[getter]
+ fn name(&self) -> String {
+ self.0.name.clone()
+ }
+
+ // TODO: Use function id.
+ #[getter]
+ fn method_id(&self) -> u32 {
+ self.0.name.as_str().as_getter_method_id()
+ }
+
+ // TODO: Use function id.
+ fn call<'a>(
+ &self,
+ py: Python<'a>,
+ account_state: &AccountState,
+ input: &PyDict,
+ clock: Option<&Clock>,
+ config: Option,
+ ) -> PyResult {
+ let input = parse_tokens(&self.0.inputs, input)?;
+ let clock = match clock {
+ Some(clock) => clock.as_ref(),
+ None => &nt::utils::SimpleClock,
+ };
+
+ let input = input
+ .into_iter()
+ .map(|item| token_to_stack_item(item.value))
+ .collect::>>()?;
+
+ let config = match &config {
+ Some(config) => nt::abi::BriefBlockchainConfig::from(config.as_ref()),
+ None => nt::abi::BriefBlockchainConfig::default(),
+ };
+
+ let ctx = nt::abi::ExecutionContext {
+ clock,
+ account_stuff: &account_state.0,
+ // TODO: Add support for libraries
+ libraries: &[],
+ }
+ .run_getter_ext(self.0.name.as_str(), &input, &config, &Default::default())
+ .handle_runtime_error()?;
+
+ drop(input);
+
+ Ok(ExecutionOutput {
+ exit_code: ctx.exit_code,
+ output: (ctx.exit_code == 0)
+ .then(|| {
+ if ctx.stack.len() != self.0.outputs.len() {
+ return Err(PyRuntimeError::new_err("Output stack size mismatch"));
+ }
+
+ let outputs = self
+ .0
+ .outputs
+ .iter()
+ .zip(ctx.stack)
+ .map(|(param, value)| {
+ let value = stack_item_to_token(¶m.kind, &value)?;
+ Ok(ton_abi::Token::new(¶m.name, value))
+ })
+ .collect::>>()?;
+
+ Ok(convert_tokens(py, outputs)?.into_py(py))
+ })
+ .transpose()?,
+ })
+ }
+
+ fn __repr__(&self) -> String {
+ format!(
+ "",
+ self.0.name, self.0.input_id
+ )
+ }
+
+ fn __hash__(&self) -> u64 {
+ self.0.input_id as u64
+ }
+
+ fn __richcmp__(&self, other: &Self, op: pyo3::basic::CompareOp) -> bool {
+ match op {
+ pyo3::basic::CompareOp::Eq => self.0.eq(&other.0),
+ pyo3::basic::CompareOp::Ne => !self.0.eq(&other.0),
+ pyo3::basic::CompareOp::Lt => self.0.input_id < other.0.input_id,
+ pyo3::basic::CompareOp::Le => self.0.input_id <= other.0.input_id,
+ pyo3::basic::CompareOp::Gt => self.0.input_id > other.0.input_id,
+ pyo3::basic::CompareOp::Ge => self.0.input_id >= other.0.input_id,
+ }
+ }
+}
+
#[pyclass(extends = Message)]
pub struct SignedExternalMessage {
pub expire_at: u32,
@@ -1022,13 +1318,13 @@ impl UnsignedExternalMessage {
self.state_init = state_init;
}
- fn sign(
+ fn sign<'a>(
&self,
- py: Python<'_>,
+ py: Python<'a>,
keypair: &KeyPair,
- signature_id: Option,
+ context: &'a PyAny,
) -> PyResult> {
- self.fill_body(py, self.body.sign(keypair, signature_id)?)
+ self.fill_body(py, self.body.sign(keypair, context)?)
}
fn with_signature(
@@ -1084,8 +1380,8 @@ impl UnsignedBody {
self.expire_at
}
- fn sign(&self, keypair: &KeyPair, signature_id: Option) -> PyResult {
- let signature = keypair.sign_raw(self.hash.as_ref(), signature_id);
+ fn sign(&self, keypair: &KeyPair, context: &PyAny) -> PyResult| {
+ let signature = keypair.sign_raw(self.hash.as_ref(), context)?;
self.fill_signature(Some(signature.0.as_ref()))
}
@@ -1163,6 +1459,7 @@ define_abi_types! {
ton_abi::ParamType::Map(key_type, value_type)
},
AbiAddress = | | ton_abi::ParamType::Address,
+ AbiAddressStd = | | ton_abi::ParamType::AddressStd,
AbiBytes = | | ton_abi::ParamType::Bytes,
AbiFixedBytes = |len: usize| ton_abi::ParamType::FixedBytes(len),
AbiString = | | ton_abi::ParamType::String,
@@ -1346,6 +1643,17 @@ fn parse_token(param: &ton_abi::ParamType, value: &PyAny) -> PyResult ton_block::MsgAddress::AddrVar(addr),
})
}
+ ton_abi::ParamType::AddressStd => {
+ let Address(addr) = value.extract::()?;
+ ton_abi::TokenValue::Address(match addr {
+ ton_block::MsgAddressInt::AddrStd(addr) => ton_block::MsgAddress::AddrStd(addr),
+ ton_block::MsgAddressInt::AddrVar(_) => {
+ return Err(PyValueError::new_err(
+ "Expected `addr_std` instead of `addr_var`",
+ ))
+ }
+ })
+ }
ton_abi::ParamType::Bytes => {
let bytes = value.extract::<&[u8]>()?;
ton_abi::TokenValue::Bytes(bytes.to_vec())
@@ -1448,7 +1756,7 @@ fn parse_map_entry_token(
Ok((key, value))
}
-pub fn convert_tokens(py: Python, tokens: Vec) -> PyResult<&PyDict> {
+pub fn convert_tokens(py: Python<'_>, tokens: Vec) -> PyResult<&PyDict> {
let result = PyDict::new(py);
for token in tokens {
result.set_item(&token.name, convert_token(py, token.value)?)?;
@@ -1482,6 +1790,7 @@ fn convert_token(py: Python, value: ton_abi::TokenValue) -> PyResult {
PyList::new(py, items).to_object(py)
}
ton_abi::TokenValue::Address(addr) => convert_addr_token(py, addr)?,
+ ton_abi::TokenValue::AddressStd(addr) => convert_addr_token(py, addr)?,
ton_abi::TokenValue::Bytes(bytes) | ton_abi::TokenValue::FixedBytes(bytes) => {
PyBytes::new(py, &bytes).to_object(py)
}
@@ -1549,3 +1858,580 @@ pub fn default_headers(
(expire_at, header)
}
+
+#[pyclass]
+pub struct TupleReader {
+ items: Vec,
+}
+
+impl TupleReader {
+ fn from_items(mut items: Vec) -> Self {
+ items.reverse();
+ Self { items }
+ }
+
+ fn pop_impl(&mut self) -> PyResult {
+ match self.items.pop() {
+ Some(item) => Ok(item),
+ None => Err(PyEOFError::new_err("Tuple is empty")),
+ }
+ }
+
+ fn read_as_lisp_list<'a>(
+ py: Python<'a>,
+ mut tail: Option<&[ton_vm::stack::StackItem]>,
+ ) -> PyResult> {
+ let mut result = Vec::new();
+ while let Some(t) = tail {
+ let [next, value] = t else {
+ return Err(PyValueError::new_err(format!(
+ "Expected tuple of two items, got {}",
+ t.len()
+ )));
+ };
+
+ result.push(convert_stack_item(py, value)?);
+ tail = match next {
+ ton_vm::stack::StackItem::None => None,
+ ton_vm::stack::StackItem::Tuple(items) => Some(items.as_slice()),
+ _ => return Err(PyTypeError::new_err("Expected tail to be null or tuple")),
+ }
+ }
+
+ Ok(result)
+ }
+}
+
+#[pymethods]
+impl TupleReader {
+ #[new]
+ pub fn new(items: &PySequence) -> PyResult {
+ parse_stack_items(items).map(Self::from_items)
+ }
+
+ #[getter]
+ pub fn remaining(&self) -> usize {
+ self.items.len()
+ }
+
+ pub fn into_inner<'a>(&self, py: Python<'a>) -> PyResult<&'a PyTuple> {
+ let mut items = self.items.clone();
+ items.reverse();
+ convert_stack_items(py, &items)
+ }
+
+ pub fn peek<'a>(&self, py: Python<'a>) -> PyResult {
+ match self.items.last() {
+ Some(item) => convert_stack_item(py, item),
+ None => Err(PyEOFError::new_err("Tuple is empty")),
+ }
+ }
+
+ pub fn pop<'a>(&mut self, py: Python<'a>) -> PyResult {
+ match self.items.pop() {
+ Some(item) => convert_stack_item(py, &item),
+ None => Err(PyEOFError::new_err("Tuple is empty")),
+ }
+ }
+
+ pub fn skip(&mut self, n: usize) -> PyResult<()> {
+ if let Some(remaining) = self.items.len().checked_sub(n) {
+ self.items.truncate(remaining);
+ Ok(())
+ } else {
+ self.items.clear();
+ Err(PyEOFError::new_err(
+ "Tuple does not contain enough items to skip",
+ ))
+ }
+ }
+
+ pub fn read_int(&mut self) -> PyResult {
+ if let ton_vm::stack::StackItem::Integer(ref int) = self.pop_impl()? {
+ if let Ok(int) = int.take_value_of(move |int| Some(int.clone())) {
+ return Ok(int);
+ }
+ }
+ Err(PyTypeError::new_err("Not a number"))
+ }
+
+ pub fn read_int_opt(&mut self) -> PyResult | | | | | | | |