Skip to content

Commit

Permalink
Merge pull request #4 from disintar/dev-nightly
Browse files Browse the repository at this point in the history
Add func
  • Loading branch information
tvorogme authored May 21, 2024
2 parents ac1adaa + b7dce6e commit 7225a71
Show file tree
Hide file tree
Showing 7 changed files with 464 additions and 5 deletions.
29 changes: 26 additions & 3 deletions src/tonpy/fift/fift.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
# Copyright (c) 2023 Disintar LLP Licensed under the Apache License Version 2.0

from pathlib import Path
import os

from tonpy.libs.python_ton import PyFift
from pathlib import Path

from tonpy import Cell
from tonpy.libs.python_ton import PyFift, func_string_to_asm, func_to_asm
from tonpy.types import Stack

libs_root = Path(__file__).parents[0]
Expand Down Expand Up @@ -48,3 +47,27 @@ def convert_assembler(assembler_code: str) -> Cell:
f.add_lib("Asm.fif")
f.run(assembler_code)
return f.last()


def func_to_assembler(sources: list[str],
preamble: bool = False,
indent: int = 0,
verbosity: bool = False,
optimization: int = 2,
envelope: bool = True,
stack_comments: bool = False,
op_comments: bool = False) -> str:
result = func_to_asm(sources, preamble, indent, verbosity, optimization, envelope, stack_comments, op_comments)
return result


def func_string_to_assembler(source: str,
preamble: bool = False,
indent: int = 0,
verbosity: bool = False,
optimization: int = 2,
envelope: bool = True,
stack_comments: bool = False,
op_comments: bool = False) -> str:
result = func_string_to_asm(source, preamble, indent, verbosity, optimization, envelope, stack_comments, op_comments)
return result
145 changes: 145 additions & 0 deletions src/tonpy/tests/test-nft-item/nft-item.fc
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
;;
;; TON NFT Item Smart Contract
;;

{-

NOTE that this tokens can be transferred within the same workchain.

This is suitable for most tokens, if you need tokens transferable between workchains there are two solutions:

1) use more expensive but universal function to calculate message forward fee for arbitrary destination (see `misc/forward-fee-calc.cs`)

2) use token holder proxies in target workchain (that way even 'non-universal' token can be used from any workchain)

-}

int min_tons_for_storage() asm "50000000 PUSHINT"; ;; 0.05 TON

;;
;; Storage
;;
;; uint64 index
;; MsgAddressInt collection_address
;; MsgAddressInt owner_address
;; cell content
;;

(int, int, slice, slice, cell) load_data() {
slice ds = get_data().begin_parse();
var (index, collection_address) = (ds~load_uint(64), ds~load_msg_addr());
if (ds.slice_bits() > 0) {
return (-1, index, collection_address, ds~load_msg_addr(), ds~load_ref());
} else {
return (0, index, collection_address, null(), null()); ;; nft not initialized yet
}
}

() store_data(int index, slice collection_address, slice owner_address, cell content) impure {
set_data(
begin_cell()
.store_uint(index, 64)
.store_slice(collection_address)
.store_slice(owner_address)
.store_ref(content)
.end_cell()
);
}

() send_msg(slice to_address, int amount, int op, int query_id, builder payload, int send_mode) impure inline {
var msg = begin_cell()
.store_uint(0x10, 6) ;; nobounce - int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool src:MsgAddress -> 010000
.store_slice(to_address)
.store_coins(amount)
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_uint(op, 32)
.store_uint(query_id, 64);

if (~ builder_null?(payload)) {
msg = msg.store_builder(payload);
}

send_raw_message(msg.end_cell(), send_mode);
}

() transfer_ownership(int my_balance, int index, slice collection_address, slice owner_address, cell content, slice sender_address, int query_id, slice in_msg_body, int fwd_fees) impure inline {
throw_unless(401, equal_slices(sender_address, owner_address));

slice new_owner_address = in_msg_body~load_msg_addr();
force_chain(new_owner_address);
slice response_destination = in_msg_body~load_msg_addr();
in_msg_body~load_int(1); ;; this nft don't use custom_payload
int forward_amount = in_msg_body~load_coins();
throw_unless(708, slice_bits(in_msg_body) >= 1);

int rest_amount = my_balance - min_tons_for_storage();
if (forward_amount) {
rest_amount -= (forward_amount + fwd_fees);
}
int need_response = response_destination.preload_uint(2) != 0; ;; if NOT addr_none: 00
if (need_response) {
rest_amount -= fwd_fees;
}

throw_unless(402, rest_amount >= 0); ;; base nft spends fixed amount of gas, will not check for response

if (forward_amount) {
send_msg(new_owner_address, forward_amount, op::ownership_assigned(), query_id, begin_cell().store_slice(owner_address).store_slice(in_msg_body), 1); ;; paying fees, revert on errors
}
if (need_response) {
force_chain(response_destination);
send_msg(response_destination, rest_amount, op::excesses(), query_id, null(), 1); ;; paying fees, revert on errors
}

store_data(index, collection_address, new_owner_address, content);
}

() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {
if (in_msg_body.slice_empty?()) { ;; ignore empty messages
return ();
}

slice cs = in_msg_full.begin_parse();
int flags = cs~load_uint(4);

if (flags & 1) { ;; ignore all bounced messages
return ();
}
slice sender_address = cs~load_msg_addr();

cs~load_msg_addr(); ;; skip dst
cs~load_coins(); ;; skip value
cs~skip_bits(1); ;; skip extracurrency collection
cs~load_coins(); ;; skip ihr_fee
int fwd_fee = muldiv(cs~load_coins(), 3, 2); ;; we use message fwd_fee for estimation of forward_payload costs


(int init?, int index, slice collection_address, slice owner_address, cell content) = load_data();
if (~ init?) {
throw_unless(405, equal_slices(collection_address, sender_address));
store_data(index, collection_address, in_msg_body~load_msg_addr(), in_msg_body~load_ref());
return ();
}

int op = in_msg_body~load_uint(32);
int query_id = in_msg_body~load_uint(64);

if (op == op::transfer()) {
transfer_ownership(my_balance, index, collection_address, owner_address, content, sender_address, query_id, in_msg_body, fwd_fee);
return ();
}
if (op == op::get_static_data()) {
send_msg(sender_address, 0, op::report_static_data(), query_id, begin_cell().store_uint(index, 256).store_slice(collection_address), 64); ;; carry all the remaining value of the inbound message
return ();
}
throw(0xffff);
}

;;
;; GET Methods
;;

(int, int, slice, slice, cell) get_nft_data() method_id {
(int init?, int index, slice collection_address, slice owner_address, cell content) = load_data();
return (init?, index, collection_address, owner_address, content);
}
12 changes: 12 additions & 0 deletions src/tonpy/tests/test-nft-item/op-codes.fc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
int op::transfer() asm "0x5fcc3d14 PUSHINT";
int op::ownership_assigned() asm "0x05138d91 PUSHINT";
int op::excesses() asm "0xd53276db PUSHINT";
int op::get_static_data() asm "0x2fcb26a2 PUSHINT";
int op::report_static_data() asm "0x8b771735 PUSHINT";
int op::get_royalty_params() asm "0x693d3950 PUSHINT";
int op::report_royalty_params() asm "0xa8cb00ad PUSHINT";

;; NFTEditable
int op::edit_content() asm "0x1a0b9d51 PUSHINT";
int op::transfer_editorship() asm "0x1c04412a PUSHINT";
int op::editorship_assigned() asm "0x511a4463 PUSHINT";
6 changes: 6 additions & 0 deletions src/tonpy/tests/test-nft-item/params.fc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
int workchain() asm "0 PUSHINT";

() force_chain(slice addr) impure {
(int wc, _) = parse_std_addr(addr);
throw_unless(333, wc == workchain());
}
Loading

0 comments on commit 7225a71

Please sign in to comment.