add nft code & script
This commit is contained in:
parent
7b8b45295a
commit
21bed2c1f3
|
|
@ -0,0 +1,24 @@
|
|||
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";
|
||||
|
||||
;; SBT
|
||||
int op::request_owner() asm "0xd0c3bfea PUSHINT";
|
||||
int op::owner_info() asm "0x0dd607e3 PUSHINT";
|
||||
|
||||
int op::prove_ownership() asm "0x04ded148 PUSHINT";
|
||||
int op::ownership_proof() asm "0x0524c7ae PUSHINT";
|
||||
int op::ownership_proof_bounced() asm "0xc18e86d2 PUSHINT";
|
||||
|
||||
int op::destroy() asm "0x1f04537a PUSHINT";
|
||||
int op::revoke() asm "0x6f89f5e3 PUSHINT";
|
||||
int op::take_excess() asm "0xd136d3b3 PUSHINT";
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
int workchain() asm "0 PUSHINT";
|
||||
|
||||
() force_chain(slice addr) impure {
|
||||
(int wc, _) = parse_std_addr(addr);
|
||||
throw_unless(333, wc == workchain());
|
||||
}
|
||||
|
||||
slice null_addr() asm "b{00} PUSHSLICE";
|
||||
int flag::regular() asm "0x10 PUSHINT";
|
||||
int flag::bounce() asm "0x8 PUSHINT";
|
||||
|
|
@ -621,5 +621,7 @@ int get_seed() impure asm "RANDSEED";
|
|||
int equal_slice_bits(slice a, slice b) asm "SDEQ";
|
||||
int equal_slices(slice a, slice b) asm "SDEQ";
|
||||
|
||||
int builder_null?(builder b) asm "ISNULL";
|
||||
|
||||
;;; Concatenates two builders
|
||||
builder store_builder(builder to, builder from) asm "STBR";
|
||||
builder store_builder(builder to, builder from) asm "STBR";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,215 @@
|
|||
;; NFT collection smart contract
|
||||
|
||||
#include "imports/stdlib.fc";
|
||||
#include "imports/op-codes.fc";
|
||||
#include "imports/params.fc";
|
||||
|
||||
;; storage scheme
|
||||
;; default#_ royalty_factor:uint16 royalty_base:uint16 royalty_address:MsgAddress = RoyaltyParams;
|
||||
;; storage#_ owner_address:MsgAddress next_item_index:uint64
|
||||
;; ^[collection_content:^Cell common_content:^Cell]
|
||||
;; nft_item_code:^Cell
|
||||
;; royalty_params:^RoyaltyParams
|
||||
;; = Storage;
|
||||
|
||||
(slice, int, cell, cell, cell) load_data() inline {
|
||||
var ds = get_data().begin_parse();
|
||||
return
|
||||
(ds~load_msg_addr(), ;; owner_address
|
||||
ds~load_uint(64), ;; next_item_index
|
||||
ds~load_ref(), ;; content
|
||||
ds~load_ref(), ;; nft_item_code
|
||||
ds~load_ref() ;; royalty_params
|
||||
);
|
||||
}
|
||||
|
||||
() save_data(slice owner_address, int next_item_index, cell content, cell nft_item_code, cell royalty_params) impure inline {
|
||||
set_data(begin_cell()
|
||||
.store_slice(owner_address)
|
||||
.store_uint(next_item_index, 64)
|
||||
.store_ref(content)
|
||||
.store_ref(nft_item_code)
|
||||
.store_ref(royalty_params)
|
||||
.end_cell());
|
||||
}
|
||||
|
||||
cell calculate_nft_item_state_init(int item_index, cell nft_item_code) {
|
||||
cell data = begin_cell().store_uint(item_index, 64).store_slice(my_address()).end_cell();
|
||||
return begin_cell().store_uint(0, 2).store_dict(nft_item_code).store_dict(data).store_uint(0, 1).end_cell();
|
||||
}
|
||||
|
||||
slice calculate_nft_item_address(int wc, cell state_init) {
|
||||
return begin_cell().store_uint(4, 3)
|
||||
.store_int(wc, 8)
|
||||
.store_uint(cell_hash(state_init), 256)
|
||||
.end_cell()
|
||||
.begin_parse();
|
||||
}
|
||||
|
||||
() deploy_nft_item(int item_index, cell nft_item_code, int amount, cell nft_content) impure {
|
||||
cell state_init = calculate_nft_item_state_init(item_index, nft_item_code);
|
||||
slice nft_address = calculate_nft_item_address(workchain(), state_init);
|
||||
var msg = begin_cell()
|
||||
.store_uint(0x18, 6)
|
||||
.store_slice(nft_address)
|
||||
.store_coins(amount)
|
||||
.store_uint(4 + 2 + 1, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1)
|
||||
.store_ref(state_init)
|
||||
.store_ref(nft_content);
|
||||
send_raw_message(msg.end_cell(), 1); ;; pay transfer fees separately, revert on errors
|
||||
}
|
||||
|
||||
(int, int) encode_number_to_text(int number) inline {
|
||||
int len = 0;
|
||||
int value = 0;
|
||||
int mult = 1;
|
||||
do {
|
||||
(number, int res) = number.divmod(10);
|
||||
value = value + (res + 48) * mult;
|
||||
mult = mult * 256;
|
||||
len = len + 1;
|
||||
} until (number == 0);
|
||||
return (len, value);
|
||||
}
|
||||
|
||||
() send_royalty_params(slice to_address, int query_id, slice data) impure inline {
|
||||
var msg = begin_cell()
|
||||
.store_uint(0x10, 6) ;; nobounce - int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool packages:MsgAddress -> 011000
|
||||
.store_slice(to_address)
|
||||
.store_coins(0)
|
||||
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
|
||||
.store_uint(op::report_royalty_params(), 32)
|
||||
.store_uint(query_id, 64)
|
||||
.store_slice(data);
|
||||
send_raw_message(msg.end_cell(), 64); ;; carry all the remaining value of the inbound message
|
||||
}
|
||||
|
||||
() recv_internal(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();
|
||||
|
||||
int op = in_msg_body~load_uint(32);
|
||||
int query_id = in_msg_body~load_uint(64);
|
||||
|
||||
var (owner_address, next_item_index, content, nft_item_code, royalty_params) = load_data();
|
||||
|
||||
if (op == op::get_royalty_params()) {
|
||||
send_royalty_params(sender_address, query_id, royalty_params.begin_parse());
|
||||
return ();
|
||||
}
|
||||
|
||||
throw_unless(401, equal_slices(sender_address, owner_address));
|
||||
|
||||
|
||||
if (op == 1) { ;; deploy new nft
|
||||
int item_index = in_msg_body~load_uint(64);
|
||||
throw_unless(402, item_index <= next_item_index);
|
||||
var is_last = item_index == next_item_index;
|
||||
deploy_nft_item(item_index, nft_item_code, in_msg_body~load_coins(), in_msg_body~load_ref());
|
||||
if (is_last) {
|
||||
next_item_index += 1;
|
||||
save_data(owner_address, next_item_index, content, nft_item_code, royalty_params);
|
||||
}
|
||||
return ();
|
||||
}
|
||||
if (op == 2) { ;; batch deploy of new nfts
|
||||
int counter = 0;
|
||||
cell deploy_list = in_msg_body~load_ref();
|
||||
do {
|
||||
var (item_index, item, f?) = deploy_list~udict::delete_get_min(64);
|
||||
if (f?) {
|
||||
counter += 1;
|
||||
if (counter >= 250) { ;; Limit due to limits of action list size
|
||||
throw(399);
|
||||
}
|
||||
|
||||
throw_unless(403 + counter, item_index <= next_item_index);
|
||||
deploy_nft_item(item_index, nft_item_code, item~load_coins(), item~load_ref());
|
||||
if (item_index == next_item_index) {
|
||||
next_item_index += 1;
|
||||
}
|
||||
}
|
||||
} until ( ~ f?);
|
||||
save_data(owner_address, next_item_index, content, nft_item_code, royalty_params);
|
||||
return ();
|
||||
}
|
||||
if (op == 3) { ;; change owner
|
||||
slice new_owner = in_msg_body~load_msg_addr();
|
||||
save_data(new_owner, next_item_index, content, nft_item_code, royalty_params);
|
||||
return ();
|
||||
}
|
||||
|
||||
if (op == 0xCB33) { ;; mint nft throw next index
|
||||
in_msg_body~skip_bits(64);
|
||||
slice forward_content = in_msg_body~load_ref().begin_parse();
|
||||
(int t_len, int t_xt) = encode_number_to_text(next_item_index);
|
||||
builder mint_content = begin_cell()
|
||||
.store_ref(
|
||||
begin_cell()
|
||||
.store_uint(0x6e6674732f6d657461646174612f, 112) ;; nfts/metadata/
|
||||
.store_uint(t_xt, t_len * 8)
|
||||
.store_uint(0x2e6a736f6e, 5 * 8) ;; .json
|
||||
.end_cell()
|
||||
)
|
||||
.store_slice(forward_content);
|
||||
|
||||
deploy_nft_item(next_item_index, nft_item_code, in_msg_body~load_coins(), mint_content.end_cell());
|
||||
next_item_index += 1;
|
||||
save_data(owner_address, next_item_index, content, nft_item_code, royalty_params);
|
||||
return ();
|
||||
}
|
||||
|
||||
if (op == 0xCB38) { ;; upgrade contract
|
||||
cell new_code = in_msg_body~load_maybe_ref();
|
||||
cell new_data = in_msg_body~load_maybe_ref();
|
||||
ifnot (new_code.null?()) {
|
||||
set_code(new_code);
|
||||
}
|
||||
ifnot (new_data.null?()) {
|
||||
set_data(new_data);
|
||||
}
|
||||
return ();
|
||||
}
|
||||
|
||||
throw(0xffff);
|
||||
}
|
||||
|
||||
;; Get methods
|
||||
|
||||
(int, cell, slice) get_collection_data() method_id {
|
||||
var (owner_address, next_item_index, content, _, _) = load_data();
|
||||
slice cs = content.begin_parse();
|
||||
return (next_item_index, cs~load_ref(), owner_address);
|
||||
}
|
||||
|
||||
slice get_nft_address_by_index(int index) method_id {
|
||||
var (_, _, _, nft_item_code, _) = load_data();
|
||||
cell state_init = calculate_nft_item_state_init(index, nft_item_code);
|
||||
return calculate_nft_item_address(0, state_init);
|
||||
}
|
||||
|
||||
(int, int, slice) royalty_params() method_id {
|
||||
var (_, _, _, _, royalty) = load_data();
|
||||
slice rs = royalty.begin_parse();
|
||||
return (rs~load_uint(16), rs~load_uint(16), rs~load_msg_addr());
|
||||
}
|
||||
|
||||
cell get_nft_content(int index, cell individual_nft_content) method_id {
|
||||
var (_, _, content, _, _) = load_data();
|
||||
slice cs = content.begin_parse();
|
||||
cs~load_ref();
|
||||
slice common_content = cs~load_ref().begin_parse();
|
||||
return (begin_cell()
|
||||
.store_uint(1, 8) ;; offchain tag
|
||||
.store_slice(common_content)
|
||||
.store_ref(individual_nft_content)
|
||||
.end_cell());
|
||||
}
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
;;
|
||||
;; TON NFT Item Smart Contract v2
|
||||
;; support ownership_assigned on minting nft
|
||||
;;
|
||||
|
||||
{-
|
||||
|
||||
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 below 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)
|
||||
|
||||
-}
|
||||
|
||||
#include "imports/stdlib.fc";
|
||||
#include "imports/op-codes.fc";
|
||||
#include "imports/params.fc";
|
||||
|
||||
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 -> 011000
|
||||
.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();
|
||||
|
||||
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));
|
||||
var new_owner_address = in_msg_body~load_msg_addr();
|
||||
store_data(index, collection_address, new_owner_address, in_msg_body~load_ref());
|
||||
if (in_msg_body.slice_data_empty?() == false) {
|
||||
var forward_amount = in_msg_body~load_coins();
|
||||
if (forward_amount) {
|
||||
send_msg(new_owner_address, forward_amount, op::ownership_assigned(), 0, begin_cell().store_slice(collection_address).store_slice(in_msg_body), 3); ;; paying fees, ignore errors
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
from base64 import b64encode
|
||||
|
||||
from tonsdk.contract.token.nft import NFTCollection, NFTItem
|
||||
from tonsdk.contract.wallet import Wallets
|
||||
import os
|
||||
import asyncio
|
||||
|
||||
from tonsdk.utils import Address
|
||||
import httpx
|
||||
import time
|
||||
|
||||
WALLET_MNEMONIC = os.getenv('WALLET_MNEMONIC', 'lucky odor welcome cool climb cream sauce either piece embark ritual purpose bacon timber please nest paddle obscure student wheel police speak acquire cream').split(' ')
|
||||
WALLET_VERSION = os.getenv('WALLET_VERSION', 'v3r2')
|
||||
|
||||
|
||||
async def main():
|
||||
_, _, _, wallet = Wallets.from_mnemonics(WALLET_MNEMONIC, WALLET_VERSION)
|
||||
print(f"Wallet address: {wallet.address.to_string(1, 1, 1)}")
|
||||
|
||||
collection = NFTCollection(
|
||||
code='b5ee9c724102160100029f000114ff00f4a413f4bcf2c80b01020162020f0202cd030a04e9d10638048adf000e8698180b8d848adf07d201800e98fe99ff6a2687d20699fea6a6a184108349e9ca829405d47141baf8280e8410854658056b84008646582a802e78b127d010a65b509e58fe59f80e78b64c0207d80701b28b9e382f970c892e000f18112e001718112e001f18112c1006599dd40405060700603502d33f5313bbf2e1925313ba01fa00d43028103459f0068e1201a44343c85005cf1613cb3fccccccc9ed54925f05e200a6357003d4308e378040f4966fa5208e2906a4208100fabe93f2c18fde81019321a05325bbf2f402fa00d43022544b30f00623ba9302a402de04926c21e2b3e6303250444313c85005cf1613cb3fccccccc9ed54002c323401fa40304144c85005cf1613cb3fccccccc9ed5402fe8e6d35028040d721d401d0237020718e14037aa90ca63024a812a003aa0702a421c0004430e6306c1282182e6a736f6e82606e6674732f6d657461646174612fc8cb6f03aa0213cf01cb27c9c8cc01cf1601fa003001c923544730f00601a44343c85005cf1613cb3fccccccc9ed54e010345f04328200cb38bae30230840f0809002cf404f40430216e91319301fb04e2206e913092ed54e20004f2f00201200b0e0201200c0d002d007232cffe0a33c5b25c083232c044fd003d0032c03260001b3e401d3232c084b281f2fff27420003d45af0047021f005778018c8cb0558cf165004fa0213cb6b12ccccc971fb008020120101502012011120043b8b5d31ed44d0fa40d33fd4d4d43010245f04d0d431d430d071c8cb0701cf16ccc980201201314002fb5dafda89a1f481a67fa9a9a860d883a1a61fa61ff480610002db4f47da89a1f481a67fa9a9a86028be09e008e003e00b00025bc82df6a2687d20699fea6a6a182de86a182c4699353e6',
|
||||
owner_address=Address('EQC6VQVXeuRdLqFmbAdeJywe2pO7eyasZTWqVdHKo-vdgsBE'),
|
||||
collection_content_uri='https://geton.farm/nfts/collection/meta.json',
|
||||
nft_item_content_base_uri='https://geton.farm/nfts/collection/',
|
||||
nft_item_code_hex='b5ee9c7241020e01000229000114ff00f4a413f4bcf2c80b01020162020d0202ce030a020120040903b90c8871c02497c0f83434c0c05c6c2497c0f83e903e900c7e800c5c75c87e800c7e800c1cea6d003c00812cf8c081b4c7f4cfe08417f30f45148c2ea3a24c840dd78c9004f6cf380c0d0d0d4d60840bf2c9a884aeb8c097c12103fcbc2005060800ca306c22345232c705f2e19501fa40d45423405235f00321c701c0008e4401fa00218e3a821005138d9170c85006cf1658cf161034413073708010c8cb055007cf165005fa0215cb6a12cb1fcb3f226eb39458cf17019132e201c901fb00925f04e2925f03e201f65135c705f2e191fa4021f001fa40d20031fa00820afaf0801ba121945315a0a1de22d70b01c300209206a19136e220c2fff2e192218e3e821005138d91c85009cf16500bcf16712449145446a0708010c8cb055007cf165005fa0215cb6a12cb1fcb3f226eb39458cf17019132e201c901fb00104794102a375be2070082028e3526f0018210d53276db103744006d71708010c8cb055007cf165005fa0215cb6a12cb1fcb3f226eb39458cf17019132e201c901fb0093303234e25502f00300727082108b77173505c8cbff5004cf1610248040708010c8cb055007cf165005fa0215cb6a12cb1fcb3f226eb39458cf17019132e201c901fb0000113e910c1c2ebcb853600201200b0c003b3b513434cffe900835d27080269fc07e90350c04090408f80c1c165b5b60001d00f232cfd633c58073c5b3327b55200009a11f9fe005df38d804',
|
||||
royalty=0.2,
|
||||
royalty_address=Address('UQDLahdbuqdPW7YoFP5_HxIcVrraziR6IBmeEYgruHCntCrb'),
|
||||
)
|
||||
print(f"Collection address: {collection.address.to_string(1, 1, 1)}")
|
||||
|
||||
wallet_seqno = httpx.get(f'https://tonapi.io/v2/blockchain/accounts/{wallet.address.to_string(1, 1, 1)}/methods/seqno').json()
|
||||
print("Wallet seqno response:", wallet_seqno)
|
||||
try:
|
||||
assert not ('error' in wallet_seqno)
|
||||
assert wallet_seqno['exit_code'] == 0
|
||||
wallet_seqno = int(wallet_seqno['stack'][0]['num'], 16)
|
||||
except:
|
||||
wallet_seqno = 0
|
||||
|
||||
print(f"Wallet seqno: {wallet_seqno}")
|
||||
# time.sleep(4)
|
||||
|
||||
query = wallet.create_transfer_message(
|
||||
collection.address.to_string(0, 1, 1),
|
||||
2e7,
|
||||
wallet_seqno,
|
||||
state_init=collection.create_state_init()['state_init']
|
||||
)
|
||||
print(
|
||||
httpx.post(
|
||||
'https://toncenter.com/api/v2/sendBoc',
|
||||
json={
|
||||
'boc': b64encode(query['message'].to_boc(False)).decode()
|
||||
}
|
||||
).json()
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
loop = asyncio.new_event_loop()
|
||||
loop.run_until_complete(main())
|
||||
loop.close()
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import { CompilerConfig } from '@ton/blueprint';
|
||||
|
||||
export const compile: CompilerConfig = {
|
||||
lang: 'func',
|
||||
targets: ['contracts/nft_collection.fc'],
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import { CompilerConfig } from '@ton/blueprint';
|
||||
|
||||
export const compile: CompilerConfig = {
|
||||
lang: 'func',
|
||||
targets: ['contracts/nft_item.fc'],
|
||||
};
|
||||
Loading…
Reference in New Issue