Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
38d24f3
Add the ability to create unsigned wallet_v5 payload
MrWad3r Sep 12, 2025
49b7cdb
Add the ability to create unsigned message body from state init + seq…
MrWad3r Sep 15, 2025
69f329a
Add tests to check signature_with_id for wallet v5
MrWad3r Sep 16, 2025
0ad3424
feat(TokenWallet): add support for optional remaining gas address in …
Odrin Sep 22, 2025
17e2063
Merge pull request #28 from Odrin/feat/token_wallet_remaining_gas
serejkaaa512 Sep 22, 2025
6cd32a1
Add libraries to run local
serejkaaa512 Aug 27, 2025
c6301a9
Always enable CapSetLibCode
MrWad3r Oct 1, 2025
1950da0
Fix unpack_from_cell last param
MrWad3r Nov 3, 2025
ad1d9df
Add burn notification to jetton parsing
serejkaaa512 Nov 28, 2025
9c87c3d
Add test to burn notification parsing
serejkaaa512 Nov 28, 2025
8691d55
Update README.md
Rexagon Dec 10, 2025
3495719
Fix working with addresses in abi
Rexagon Dec 11, 2025
64ce360
Fix `address_only_hash` for `addr_none`
Rexagon Dec 11, 2025
0912b4f
add jennot internal transfer parsing in token wallet handle block
serejkaaa512 Dec 5, 2025
50e266e
dont mix parsing jetton and tip3 tokens
pashinov Dec 15, 2025
692f199
feat: use signature domain instead of signature id for signatures
MrWad3r Jan 28, 2026
604213f
feat: use signature context to determine which signature scheme shoul…
MrWad3r Jan 29, 2026
78830a9
Add signature_context to NetworkCapabilities
MrWad3r Feb 9, 2026
6cca539
fix: move `signature_domain` to `nekoton_utils`. Fix signature type s…
MrWad3r Feb 9, 2026
d3731c5
fix: SignatureDomain signature check
MrWad3r Feb 12, 2026
610d528
fix: WalletType for WalletV5R1
pashinov Feb 15, 2026
7b4e5ee
fix: use prepend_raw in sign_with_pruned_payload for wallet v3/v4
pashinov Feb 19, 2026
9b79453
feat: add support wallets v3/v4 for ledger
pashinov Feb 19, 2026
3e5b1ca
feat: promote `run_local` to responsible when `externalMsg: false`
Rexagon Jun 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "nekoton"
version = "0.13.1"
version = "0.14.0"
authors = [
"Alexey Pashinov <pashinov93@gmail.com>",
"Vladimir Petrzhikovskiy <v.petrzhikovskiy@dexpa.io>",
Expand Down Expand Up @@ -45,7 +45,7 @@ quick_cache = "0.4.1"
rand = { version = "0.8", features = ["getrandom"], optional = true }
secstr = { version = "0.5.0", features = ["serde"], optional = true }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_json = { version = "1.0", features = ["raw_value"] }
sha2 = { version = "0.10.8", optional = true }
thiserror = "1.0"
tiny-jsonrpc = { version = "0.6.0", default-features = false, optional = true }
Expand All @@ -58,7 +58,7 @@ tiny-hderive = { git = "https://github.com/broxus/tiny-hderive.git", optional =

ton_abi = { git = "https://github.com/broxus/ton-labs-abi" }
ton_block = { git = "https://github.com/broxus/ton-labs-block.git" }
ton_executor = { git = "https://github.com/broxus/ton-labs-executor.git" }
ton_executor = { git = "https://github.com/broxus/ton-labs-executor.git"}
ton_types = { git = "https://github.com/broxus/ton-labs-types.git" }

nekoton-contracts = { path = "nekoton-contracts" }
Expand Down
12 changes: 0 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
<p align="center">
<a href="https://github.com/venom-blockchain/developer-program">
<img src="https://raw.githubusercontent.com/venom-blockchain/developer-program/main/vf-dev-program.png" alt="Logo" width="366.8" height="146.4">
</a>
</p>

# nekoton &emsp; [![Workflow badge]][workflow] [![License Apache badge]][license apache] [![Docs badge]][docs]

## About

Broxus SDK with TIP3 wallets support and a bunch of helpers.

## Usage

```bash
cargo add nekoton
```

### Prerequisites

- Rust 1.65+
Expand Down
2 changes: 1 addition & 1 deletion gen-protos/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "gen-protos"
description = "Generate Protocol Buffers definitions for nekoton-proto crate"
version = "0.13.0"
version = "0.14.0"
authors = [
"Alexey Pashinov <pashinov93@gmail.com>",
"Vladimir Petrzhikovskiy <v.petrzhikovskiy@dexpa.io>",
Expand Down
2 changes: 1 addition & 1 deletion nekoton-abi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "nekoton-abi"
version = "0.13.0"
version = "0.14.0"
authors = [
"Alexey Pashinov <pashinov93@gmail.com>",
"Vladimir Petrzhikovskiy <v.petrzhikovskiy@dexpa.io>",
Expand Down
25 changes: 9 additions & 16 deletions nekoton-abi/src/abi_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use ton_types::UInt256;

use super::{BuildTokenValue, KnownParamType, UnpackerError, UnpackerResult};

#[derive(Clone, Debug)]
pub struct BigUint128(pub BigUint);

impl BuildTokenValue for BigUint128 {
Expand Down Expand Up @@ -206,7 +207,13 @@ pub mod address_only_hash {
TokenValue::Address(ton_block::MsgAddress::AddrStd(ton_block::MsgAddrStd {
address,
..
}))
| TokenValue::AddressStd(ton_block::MsgAddress::AddrStd(ton_block::MsgAddrStd {
address,
..
})) => Ok(UInt256::from_be_bytes(&address.get_bytestring(0))),
TokenValue::Address(ton_block::MsgAddress::AddrNone)
| TokenValue::AddressStd(ton_block::MsgAddress::AddrNone) => Ok(UInt256::ZERO),
_ => Err(UnpackerError::InvalidAbi),
}
}
Expand All @@ -222,16 +229,7 @@ pub mod array_address_only_hash {
pub fn pack(value: Vec<UInt256>) -> TokenValue {
TokenValue::Array(
param_type(),
value
.into_iter()
.map(|value| {
TokenValue::Address(ton_block::MsgAddress::AddrStd(ton_block::MsgAddrStd {
anycast: None,
workchain_id: 0,
address: value.into(),
}))
})
.collect(),
value.into_iter().map(address_only_hash::pack).collect(),
)
}

Expand All @@ -240,12 +238,7 @@ pub mod array_address_only_hash {
TokenValue::Array(_, values) => {
let mut result = Vec::with_capacity(values.len());
for value in values {
match value {
TokenValue::Address(ton_block::MsgAddress::AddrStd(
ton_block::MsgAddrStd { address, .. },
)) => result.push(UInt256::from_be_bytes(&address.get_bytestring(0))),
_ => return Err(UnpackerError::InvalidAbi),
}
result.push(address_only_hash::unpack(value)?);
}
Ok(result)
}
Expand Down
9 changes: 9 additions & 0 deletions nekoton-abi/src/function_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub struct FunctionBuilder {
outputs: Vec<Param>,
/// Whether `answer_id` is set
responsible: bool,
/// Whether the function can be executed as external message.
external_msg: Option<bool>,
}

impl FunctionBuilder {
Expand All @@ -36,11 +38,13 @@ impl FunctionBuilder {
inputs: Vec::new(),
outputs: Vec::new(),
responsible: false,
external_msg: None,
}
}

pub fn new_responsible(function_name: &str) -> Self {
let mut function = Self::new(function_name);
// Force all responsible functions to be called as internal.
function.make_responsible();
function
}
Expand Down Expand Up @@ -71,6 +75,10 @@ impl FunctionBuilder {
self.responsible = true;
}

pub fn external_msg(&mut self, external_msg: Option<bool>) {
self.external_msg = external_msg;
}

pub fn abi_version(mut self, abi_version: AbiVersion) -> Self {
self.abi_version = abi_version;
self
Expand Down Expand Up @@ -140,6 +148,7 @@ impl FunctionBuilder {
outputs: self.outputs,
input_id: 0,
output_id: 0,
external_msg: self.external_msg,
};
match self.id {
Some(id) => {
Expand Down
71 changes: 62 additions & 9 deletions nekoton-abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ use ton_block::{
Serializable,
};
use ton_executor::{BlockchainConfig, OrdinaryTransactionExecutor, TransactionExecutor};
use ton_types::{SliceData, UInt256};
use ton_types::{HashmapE, SliceData, UInt256};
use ton_vm::executor::BehaviorModifiers;

#[cfg(feature = "derive")]
Expand Down Expand Up @@ -248,7 +248,7 @@ pub fn unpack_from_cell(
) -> Result<Vec<Token>> {
let cs: Cursor = cursor.into();
let (tokens, cursor) =
TokenValue::decode_params_with_cursor(params, cs, &abi_version, allow_partial, false)?;
TokenValue::decode_params_with_cursor(params, cs, &abi_version, allow_partial, true)?;

if !allow_partial
&& (cursor.slice.remaining_references() != 0 || cursor.slice.remaining_bits() != 0)
Expand Down Expand Up @@ -590,19 +590,30 @@ pub fn code_to_tvc(code: ton_types::Cell) -> Result<ton_block::StateInit> {
pub struct ExecutionContext<'a> {
pub clock: &'a dyn Clock,
pub account_stuff: &'a AccountStuff,
pub libraries: &'a [HashmapE],
}

impl ExecutionContext<'_> {
pub fn run_local(&self, function: &Function, input: &[Token]) -> Result<ExecutionOutput> {
function.run_local(self.clock, self.account_stuff.clone(), input)
function.run_local(
self.clock,
self.account_stuff.clone(),
input,
self.libraries,
)
}

pub fn run_local_responsible(
&self,
function: &Function,
input: &[Token],
) -> Result<ExecutionOutput> {
function.run_local_responsible(self.clock, self.account_stuff.clone(), input)
function.run_local_responsible(
self.clock,
self.account_stuff.clone(),
input,
self.libraries,
)
}

pub fn run_getter<M>(
Expand Down Expand Up @@ -643,6 +654,7 @@ impl ExecutionContext<'_> {
args,
config,
modifier,
self.libraries,
)
}
}
Expand Down Expand Up @@ -684,13 +696,15 @@ pub trait FunctionExt {
clock: &dyn Clock,
account_stuff: AccountStuff,
input: &[Token],
libraries: &[HashmapE],
) -> Result<ExecutionOutput> {
self.run_local_ext(
clock,
account_stuff,
input,
false,
&BriefBlockchainConfig::default(),
libraries,
)
}

Expand All @@ -699,13 +713,15 @@ pub trait FunctionExt {
clock: &dyn Clock,
account_stuff: AccountStuff,
input: &[Token],
libraries: &[HashmapE],
) -> Result<ExecutionOutput> {
self.run_local_ext(
clock,
account_stuff,
input,
true,
&BriefBlockchainConfig::default(),
libraries,
)
}

Expand All @@ -716,6 +732,7 @@ pub trait FunctionExt {
input: &[Token],
responsible: bool,
config: &BriefBlockchainConfig,
libraries: &[HashmapE],
) -> Result<ExecutionOutput>;
}

Expand All @@ -734,8 +751,17 @@ where
input: &[Token],
responsible: bool,
config: &BriefBlockchainConfig,
libraries: &[HashmapE],
) -> Result<ExecutionOutput> {
T::run_local_ext(self, clock, account_stuff, input, responsible, config)
T::run_local_ext(
self,
clock,
account_stuff,
input,
responsible,
config,
libraries,
)
}
}

Expand All @@ -752,8 +778,16 @@ impl FunctionExt for Function {
input: &[Token],
responsible: bool,
config: &BriefBlockchainConfig,
libraries: &[HashmapE],
) -> Result<ExecutionOutput> {
FunctionAbi::new(self).run_local(clock, &mut account_stuff, input, responsible, config)
FunctionAbi::new(self).run_local(
clock,
&mut account_stuff,
input,
responsible,
config,
libraries,
)
}
}

Expand All @@ -776,11 +810,18 @@ impl<'a> FunctionAbi<'a> {
clock: &dyn Clock,
account_stuff: &mut AccountStuff,
input: &[Token],
responsible: bool,
mut responsible: bool,
config: &BriefBlockchainConfig,
libraries: &[HashmapE],
) -> Result<ExecutionOutput> {
let function = self.abi;

if let Some(external_msg) = self.abi.external_msg {
// Force "upgrade" function to responsible when it cannot
// be executed as an external message.
responsible |= !external_msg;
}

let answer_id = if responsible {
account_stuff.storage.balance.grams = ton_block::Grams::from(100_000_000_000_000u64); // 100 000 TON

Expand Down Expand Up @@ -838,6 +879,7 @@ impl<'a> FunctionAbi<'a> {
&msg,
config,
&Default::default(),
libraries,
)?;

let tokens = if let Some(answer_id) = answer_id {
Expand Down Expand Up @@ -1171,13 +1213,23 @@ pub fn default_blockchain_config() -> &'static ton_executor::BlockchainConfig {
mod tests {
use std::str::FromStr;

use super::*;
use ton_abi::{Param, ParamType, Uint};
use ton_block::{Deserializable, Message, Transaction};

use super::*;
use ton_types::deserialize_tree_of_cells;

const DEFAULT_ABI_VERSION: ton_abi::contract::AbiVersion = ton_abi::contract::ABI_VERSION_2_0;

#[test]
fn string_test() {
let boc = "te6ccgEBAgEAEQABAAEAGEhlbGxvIFdvcmxkIQ==";
let cell = deserialize_tree_of_cells(&mut base64::decode(boc).unwrap().as_slice()).unwrap();
let slice = SliceData::load_cell(cell).unwrap();
let params = Param::new("boc", ParamType::String);
let tokens =
unpack_from_cell(&[params], slice, false, ton_abi::contract::ABI_VERSION_2_4).unwrap();
}

#[test]
fn correct_text_payload() {
let comment = create_boc_or_comment_payload("test").unwrap();
Expand Down Expand Up @@ -1279,6 +1331,7 @@ mod tests {
let res = ExecutionContext {
clock: &SimpleClock,
account_stuff: &state,
libraries: Default::default(),
}
.run_getter("seqno", &[])
.unwrap();
Expand Down
14 changes: 11 additions & 3 deletions nekoton-abi/src/token_unpacker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,12 +208,17 @@ impl UnpackAbi<Cell> for TokenValue {
impl UnpackAbi<MsgAddressInt> for TokenValue {
fn unpack(self) -> UnpackerResult<MsgAddressInt> {
match self {
TokenValue::Address(ton_block::MsgAddress::AddrStd(addr)) => {
TokenValue::Address(ton_block::MsgAddress::AddrStd(addr))
| TokenValue::AddressStd(ton_block::MsgAddress::AddrStd(addr)) => {
Ok(MsgAddressInt::AddrStd(addr))
}
TokenValue::Address(ton_block::MsgAddress::AddrVar(addr)) => {
Ok(MsgAddressInt::AddrVar(addr))
}
TokenValue::Address(ton_block::MsgAddress::AddrNone)
| TokenValue::AddressStd(ton_block::MsgAddress::AddrNone) => {
Ok(MsgAddressInt::AddrStd(MsgAddrStd::default()))
}
_ => Err(UnpackerError::InvalidAbi),
}
}
Expand All @@ -222,7 +227,7 @@ impl UnpackAbi<MsgAddressInt> for TokenValue {
impl UnpackAbi<MsgAddress> for TokenValue {
fn unpack(self) -> UnpackerResult<MsgAddress> {
match self {
TokenValue::Address(address) => Ok(address),
TokenValue::Address(address) | TokenValue::AddressStd(address) => Ok(address),
_ => Err(UnpackerError::InvalidAbi),
}
}
Expand All @@ -231,7 +236,10 @@ impl UnpackAbi<MsgAddress> for TokenValue {
impl UnpackAbi<MsgAddrStd> for TokenValue {
fn unpack(self) -> UnpackerResult<MsgAddrStd> {
match self {
TokenValue::Address(ton_block::MsgAddress::AddrStd(addr)) => Ok(addr),
TokenValue::Address(ton_block::MsgAddress::AddrStd(addr))
| TokenValue::AddressStd(ton_block::MsgAddress::AddrStd(addr)) => Ok(addr),
TokenValue::Address(ton_block::MsgAddress::AddrNone)
| TokenValue::AddressStd(ton_block::MsgAddress::AddrNone) => Ok(MsgAddrStd::default()),
_ => Err(UnpackerError::InvalidAbi),
}
}
Expand Down
Loading