-
Notifications
You must be signed in to change notification settings - Fork 71
/
nft-collection.fc
99 lines (82 loc) · 4.34 KB
/
nft-collection.fc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
_ unwrap_signed_cmd(slice signed_cmd, int public_key, int subwallet_id, int msg_value) {
(slice signature, int hash, int got_subwallet_id, int valid_since, int valid_till, slice cmd)
= unpack_signed_cmd(signed_cmd);
throw_unless(err::invalid_signature, check_signature(hash, signature, public_key));
throw_unless(err::wrong_subwallet_id, subwallet_id == got_subwallet_id);
int ts = now();
throw_unless(err::not_yet_valid_signature, valid_since < ts);
throw_unless(err::expired_signature, ts < valid_till);
return cmd;
}
() deploy_item(slice sender_address, int bid, cell item_code, slice cmd, slice full_domain, cell default_royalty_params) impure {
var (token_name, content, auction_config, royalty) = unpack_deploy_msg(cmd);
(slice beneficiary_address, int initial_min_bid, int max_bid, int min_bid_step, int min_extend_time, _) = unpack_auction_config(auction_config);
throw_unless(err::not_enough_funds, bid >= initial_min_bid);
int item_index = string_hash(token_name);
cell state_init = pack_item_state_init(item_index, item_code);
slice item_address = calculate_address(workchain, state_init);
if (null?(royalty)) {
royalty = default_royalty_params;
}
cell token_info = pack_token_info(token_name, full_domain);
cell deploy_msg = pack_teleitem_msg_deploy(sender_address, bid, token_info, content, auction_config, royalty);
cell msg = pack_init_int_message(item_address, state_init, deploy_msg);
send_raw_message(msg, 64); ;; carry all the remaining value of the inbound message, fee deducted from amount
}
() recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure {
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.slice_empty?() ? 0 : in_msg_body~load_uint(32);
if (op == 0) { ;; regular money transfer
;; NB: it is not possible to recover any money transferred to this account
;; so we return back all transfers except ones with comment #topup in it
throw_unless(err::wrong_topup_comment, equal_slices(in_msg_body, "#topup") & (in_msg_body.slice_refs() == 0));
return ();
}
throw_unless(err::unknown_op, op == op::telemint_msg_deploy);
var (_, subwallet_id, public_key, _, item_code, full_domain, default_royalty_params) = unpack_collection_data();
var cmd = unwrap_signed_cmd(in_msg_body, public_key, subwallet_id, msg_value);
deploy_item(sender_address, msg_value, item_code, cmd, full_domain, default_royalty_params);
}
() recv_external(slice in_msg) impure {
var (touched, subwallet_id, public_key, content, item_code, full_domain, royalty_params) = unpack_collection_data();
throw_if(err::forbidden_touch, touched);
accept_message();
save_collection_data(true, subwallet_id, public_key, content, item_code, full_domain, royalty_params);
}
;; Get methods
(int, cell, slice) get_collection_data() method_id {
var (_, _, _, content, _, _, _) = unpack_collection_data();
return (-1, content, zero_address());
}
slice get_full_domain() method_id {
var (_, _, _, _, _, full_domain, _) = unpack_collection_data();
return full_domain;
}
slice get_nft_address_by_index(int index) method_id {
var (_, _, _, _, item_code, _, _) = unpack_collection_data();
cell state_init = pack_item_state_init(index, item_code);
return calculate_address(workchain, state_init);
}
cell get_nft_content(int index, cell individual_nft_content) method_id {
return individual_nft_content;
}
(int, cell) dnsresolve(slice subdomain, int category) method_id {
throw_unless(err::bad_subdomain_length, slice_bits(subdomain) % 8 == 0);
int skipped_bits = subdomain~skip_first_zero_byte?() & 8;
if (skipped_bits & subdomain.slice_empty?()) { ;; "." requested
return (skipped_bits, null()); ;; resolved but no dns-records
}
int top_subdomain_bits = get_top_domain_bits(subdomain);
slice top_subdomain = subdomain~load_bits(top_subdomain_bits);
int item_index = string_hash(top_subdomain);
cell result = begin_cell()
.store_uint(dns_next_resolver_prefix, 16)
.store_slice(get_nft_address_by_index(item_index))
.end_cell();
return (top_subdomain_bits + skipped_bits, result);
}