@simplenft/api 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +30 -0
  2. package/blueprint.config.ts +13 -0
  3. package/contracts/buyer_profile.tact +73 -0
  4. package/contracts/imports/stdlib.fc +625 -0
  5. package/contracts/jetton_eq.tact +79 -0
  6. package/contracts/message.tact +189 -0
  7. package/contracts/nft_item.tact +98 -0
  8. package/contracts/nft_item_free.tact +98 -0
  9. package/contracts/packages/math/float.fc +95 -0
  10. package/contracts/packages/misc/distributor_messages.tact +154 -0
  11. package/contracts/packages/nap/errcodes.tact +5 -0
  12. package/contracts/packages/nap/messages.tact +34 -0
  13. package/contracts/packages/token/jetton/JettonMaster.tact +127 -0
  14. package/contracts/packages/token/jetton/JettonWallet.tact +248 -0
  15. package/contracts/packages/token/nft/AuctionErrorCode.tact +55 -0
  16. package/contracts/packages/token/nft/NFTAuction.tact +226 -0
  17. package/contracts/packages/token/nft/NFTAuctionMarket.tact +302 -0
  18. package/contracts/packages/token/nft/NFTCollection.tact +69 -0
  19. package/contracts/packages/token/nft/NFTItem.tact +190 -0
  20. package/contracts/packages/token/nft/extensions/NFTEditable.tact +3 -0
  21. package/contracts/packages/token/nft/extensions/NFTRoyalty.tact +63 -0
  22. package/contracts/packages/traits/taxable.tact +31 -0
  23. package/contracts/packages/utils/Estimatable.tact +11 -0
  24. package/contracts/packages/utils/Lockable.tact +23 -0
  25. package/contracts/sbt_item.tact +70 -0
  26. package/contracts/simple_nft_collection.tact +177 -0
  27. package/contracts/simple_nft_collection_v2.tact +304 -0
  28. package/contracts/simple_nft_master.tact +102 -0
  29. package/dist/api.d.ts +10 -0
  30. package/dist/api.js +58 -0
  31. package/dist/backend-service.d.ts +13 -0
  32. package/dist/backend-service.js +29 -0
  33. package/dist/backend-types.d.ts +60 -0
  34. package/dist/backend-types.js +2 -0
  35. package/dist/content.d.ts +3 -0
  36. package/dist/content.js +30 -0
  37. package/dist/contracts/tact_NftItem.d.ts +619 -0
  38. package/dist/contracts/tact_NftItem.js +2312 -0
  39. package/dist/contracts/tact_SimpleNftCollectionV2.d.ts +658 -0
  40. package/dist/contracts/tact_SimpleNftCollectionV2.js +2427 -0
  41. package/dist/contracts/tact_SimpleNftMaster.d.ts +624 -0
  42. package/dist/contracts/tact_SimpleNftMaster.js +2350 -0
  43. package/dist/index.d.ts +57 -0
  44. package/dist/index.js +254 -0
  45. package/dist/types.d.ts +53 -0
  46. package/dist/types.js +2 -0
  47. package/package.json +56 -0
  48. package/src/api.ts +62 -0
  49. package/src/backend-service.ts +40 -0
  50. package/src/backend-types.ts +72 -0
  51. package/src/content.ts +36 -0
  52. package/src/contracts/tact_NftItem.ts +2718 -0
  53. package/src/contracts/tact_SimpleNftCollectionV2.ts +2843 -0
  54. package/src/contracts/tact_SimpleNftMaster.ts +2759 -0
  55. package/src/index.ts +361 -0
  56. package/src/types.ts +62 -0
@@ -0,0 +1,304 @@
1
+ import "@stdlib/deploy";
2
+ import "./message.tact";
3
+ import "./nft_item.tact";
4
+ import "./sbt_item.tact";
5
+ import "./buyer_profile.tact";
6
+
7
+ const nftBalanceConst: Int = ton("0.05");
8
+ const minPriceNoProfile: Int = ton("0.039");
9
+ const whitelistUpdatePrice: Int = ton("0.009");
10
+ const massUpdateMasterFee: Int = ton("0.01");
11
+ const singleTransactionReserve: Int = ton("0.005");
12
+
13
+
14
+ contract SimpleNftCollectionV2 with Deployable {
15
+
16
+ next_item_index: Int as uint32 = 0;
17
+ collection_index: Int as uint32 = 0;
18
+ owner_address: Address?;
19
+ master_address: Address;
20
+ royalty_params: RoyaltyParams?;
21
+ collection_content: Cell?;
22
+ individual_content_url: Cell?;
23
+ mint_limit: Int as uint32 = 0;
24
+ price: Int = 0;
25
+ is_setup: Bool;
26
+ is_sbt: Int = 0;
27
+ mint_time_limit: Int as uint32 = 0;
28
+ enable_profile: Bool = false;
29
+ user_item_limit: Int as uint8 = 0;
30
+ enable_whitelist: Bool = false;
31
+
32
+ init(
33
+ master_address: Address,
34
+ collection_index: Int){
35
+ require(sender() == master_address, "Not from master");
36
+ self.collection_index = collection_index;
37
+ self.master_address = master_address;
38
+ self.is_setup = false;
39
+ }
40
+
41
+ receive(msg: CollectionSetupParams) {
42
+ require(sender() == self.master_address, "Not from master");
43
+ require(self.is_setup == false, "Collection settings is already setup");
44
+ self.price = msg.nft_price;
45
+ self.mint_limit = msg.mint_limit;
46
+ self.owner_address = msg.owner_address; // msg.owner_address;
47
+ self.royalty_params = msg.royalty_params;
48
+ self.collection_content = msg.collection_content;
49
+ self.individual_content_url = msg.nft_individual_content_url;
50
+ self.is_setup = true;
51
+ self.is_sbt = msg.is_sbt;
52
+ self.enable_profile = msg.enable_profile;
53
+ self.user_item_limit = msg.user_item_limit;
54
+ self.mint_time_limit = msg.mint_time_limit;
55
+ self.enable_whitelist = msg.enable_whitelist;
56
+ }
57
+ // Profile
58
+ get fun buyer_profile_address(owner: Address): Address{
59
+ return contractAddress(initOf BuyerProfile(myAddress(), owner));
60
+ }
61
+
62
+ receive("RequestWhitelist") {
63
+ require(self.enable_profile == true, "Profile not nessesary for this collection");
64
+ let init: StateInit = initOf BuyerProfile(myAddress(), sender());
65
+ send(SendParameters{
66
+ to: contractAddress(init),
67
+ body: SetupCollectionData{
68
+ collection_owner: self.owner_address,
69
+ collection_item_price: self.price,
70
+ enable_whitelist: self.enable_whitelist,
71
+ user_item_limit: self.user_item_limit
72
+ }.toCell(),
73
+ value: ton("0.02"),
74
+ mode: SendIgnoreErrors,
75
+ code: init.code,
76
+ data: init.data
77
+ });
78
+ }
79
+
80
+ // Classic for a free mint
81
+ receive("Mint"){
82
+ let ctx: Context = context(); // get sender Info
83
+ require(ctx.value >= self.price, "NFT creation underpriced");
84
+ require(self.enable_profile == false, "Another method for profiles");
85
+ let msgValue: Int = ctx.value;
86
+ let tonBalanceBeforeMsg: Int = myBalance() - msgValue;
87
+ let storageFee: Int = minTonsForStorage - min(tonBalanceBeforeMsg, minTonsForStorage);
88
+ msgValue = msgValue - (storageFee + gasConsumption);
89
+
90
+ self.mint(ctx.sender, msgValue);
91
+
92
+ emit(LogEventMintRecord{ minter: sender(), item_id: self.next_item_index, generate_number: nativeRandom() }.toCell());
93
+ }
94
+
95
+ receive(msg: Withdraw) {
96
+ require(sender() == self.owner_address, "Not from owner");
97
+ send(SendParameters{
98
+ to: msg.to,
99
+ value: myBalance() - masterMinStorage,
100
+ bounce: false,
101
+ mode: SendIgnoreErrors
102
+ });
103
+ }
104
+
105
+ // Mint with whitelist support
106
+ receive(msg: MintTo) {
107
+ let ownerProfile = self.get_user_profile_init(msg.owner);
108
+ require(sender() == contractAddress(ownerProfile), "From profile only");
109
+ let ctx: Context = context();
110
+ let msgValue: Int = ctx.value;
111
+ let tonBalanceBeforeMsg: Int = myBalance() - msgValue;
112
+ let storageFee: Int = minTonsForStorage - min(tonBalanceBeforeMsg, minTonsForStorage);
113
+ msgValue = msgValue - (storageFee + gasConsumption);
114
+
115
+ self.mint(msg.owner, msgValue);
116
+ }
117
+
118
+ // ===== Private Methods ===== //
119
+
120
+ fun mint(sender: Address, msgValue: Int) {
121
+ require(self.next_item_index >= 0, "non-sequential NFTs");
122
+ require(self.is_setup == true, "Collection settings is not setup");
123
+ if (self.mint_limit > 0) {
124
+ require(self.next_item_index <= self.mint_limit, "Mint limit reached");
125
+ }
126
+ if (self.mint_time_limit > 0) {
127
+ require(now() <= self.mint_time_limit, "Mint time limit reached");
128
+ }
129
+ let nft_init: StateInit = self.getNftItemInit(self.next_item_index);
130
+ let noFeeConst = self.enable_profile ? nftBalanceConst : minPriceNoProfile;
131
+ let feeValue = msgValue > noFeeConst ? msgValue - noFeeConst : 0;
132
+ send(SendParameters{
133
+ to: contractAddress(nft_init),
134
+ value: msgValue - feeValue,
135
+ bounce: false,
136
+ mode: SendIgnoreErrors,
137
+ body: Transfer {
138
+ query_id: 0,
139
+ new_owner: sender,
140
+ response_destination: self.owner_address,
141
+ custom_payload: self.individual_content_url,
142
+ forward_amount: 0,
143
+ forward_payload: emptySlice()
144
+ }.toCell(),
145
+ code: nft_init.code,
146
+ data: nft_init.data
147
+ });
148
+ if (feeValue > 0) {
149
+ send(SendParameters{
150
+ to: self.master_address,
151
+ value: (feeValue * 3) / 100,
152
+ bounce: false,
153
+ mode: SendIgnoreErrors
154
+ });
155
+
156
+ // let balanceRemaining: Int = myBalance();
157
+ send(SendParameters{
158
+ to: self.owner_address!!,
159
+ value: (feeValue * 97) / 100, // (feeValue * 97) / 100,
160
+ bounce: false,
161
+ mode: SendIgnoreErrors
162
+ });
163
+ }
164
+
165
+ dump(self.next_item_index); // Reference at: https://tact-by-example.org/03-emit
166
+ self.next_item_index = self.next_item_index + 1;
167
+ }
168
+
169
+ // -------------- Profile operations ----------------------- //
170
+ get fun get_buyer_profile_address (address: Address): Address {
171
+ let profile = self.get_user_profile_init(address);
172
+ return contractAddress(profile);
173
+ }
174
+
175
+ fun update_white_list(address: Address, add: Bool, value: Int) {
176
+ let profile = self.get_user_profile_init(address);
177
+ send(SendParameters{
178
+ to: contractAddress(profile),
179
+ body: AddToWhiteList {
180
+ add: add
181
+ }.toCell(),
182
+ value: value,
183
+ mode: SendIgnoreErrors
184
+ });
185
+ }
186
+
187
+ receive(msg: GetRoyaltyParams) {
188
+ let ctx: Context = context(); // get sender Info
189
+ send(SendParameters{
190
+ to: ctx.sender,
191
+ value: 0,
192
+ mode: 64,
193
+ bounce: false,
194
+ body: ReportRoyaltyParams {
195
+ query_id: msg.query_id,
196
+ numerator: (self.royalty_params!!).numerator,
197
+ denominator: (self.royalty_params!!).denominator,
198
+ destination: (self.royalty_params!!).destination
199
+ }.toCell()
200
+ });
201
+ }
202
+
203
+ receive(msg: UpdateWhiteList) {
204
+ require(sender() == self.owner_address, "Not a collection owner");
205
+ let ctx: Context = context();
206
+ self.update_white_list(msg.user, msg.whitelist, whitelistUpdatePrice); // ctx.value - singleTransactionReserve
207
+ }
208
+
209
+ receive(msg: MassUpdateWhiteList) {
210
+ require(sender() == self.owner_address, "Not a collection owner");
211
+ let cell = msg.addresses;
212
+ let slice = cell.beginParse();
213
+
214
+ while (true) {
215
+ let address = slice.loadAddress();
216
+ self.update_white_list(address, msg.add, msg.spendPerAddress);
217
+
218
+ if (slice.refs() > 0) {
219
+ slice = slice.loadRef().beginParse();
220
+ } else {
221
+ return;
222
+ }
223
+ }
224
+
225
+ send(SendParameters{
226
+ to: self.master_address,
227
+ value: massUpdateMasterFee,
228
+ bounce: false,
229
+ mode: SendIgnoreErrors
230
+ });
231
+ }
232
+
233
+ get fun get_master_data_v2(): CollectionMasterDataV2 {
234
+ return CollectionMasterDataV2{
235
+ master: self.master_address,
236
+ mint_limit: self.mint_limit,
237
+ mint_time_limit: self.mint_time_limit,
238
+ is_sbt: self.is_sbt,
239
+ price: self.price,
240
+ enable_whitelist: self.enable_whitelist,
241
+ index_in_collection: self.collection_index,
242
+ user_item_limit: self.user_item_limit
243
+ }
244
+ }
245
+
246
+ get fun get_master_data(): CollectionMasterData {
247
+ return CollectionMasterData{
248
+ master: self.master_address,
249
+ mint_limit: self.mint_limit,
250
+ mint_time_limit: self.mint_time_limit,
251
+ is_sbt: self.is_sbt,
252
+ price: self.price,
253
+ index_in_collection: self.collection_index
254
+ }
255
+ }
256
+
257
+ // ------------------ Get Function ------------------ //
258
+ get fun get_collection_data(): CollectionData {
259
+ let b: StringBuilder = beginString();
260
+ let collectionDataString: String = (self.collection_content!!).asSlice().asString();
261
+ b.append(collectionDataString);
262
+ return CollectionData{
263
+ next_item_index: self.next_item_index,
264
+ collection_content: b.toCell(),
265
+ owner_address: self.owner_address!!
266
+ };
267
+ }
268
+
269
+ get fun get_nft_address_by_index(item_index: Int): Address?{
270
+ let initCode: StateInit = self.getNftItemInit(item_index);
271
+ return contractAddress(initCode);
272
+ }
273
+
274
+ get fun getNftItemInit(item_index: Int): StateInit {
275
+ // return initOf NftItem(myAddress(), item_index);
276
+ if (self.is_sbt == 0) {
277
+ return initOf NftItem(myAddress(), item_index);
278
+ } else {
279
+ return initOf SbtItem(myAddress(), item_index);
280
+ }
281
+ }
282
+
283
+ get fun get_user_profile_init(address: Address): StateInit {
284
+ return initOf BuyerProfile(myAddress(), address);
285
+ }
286
+
287
+ get fun get_nft_content(index: Int, individual_content: Cell): Cell {
288
+ let b: StringBuilder = beginString();
289
+ let ic: String = individual_content.asSlice().asString();
290
+ b.append(ic);
291
+ return b.toCell();
292
+ }
293
+
294
+ get fun get_sample_nft_content (): Cell? {
295
+ let b: StringBuilder = beginString();
296
+ let ic: String = (self.individual_content_url!!).asSlice().asString();
297
+ b.append(ic);
298
+ return b.toCell();
299
+ }
300
+
301
+ get fun royalty_params(): RoyaltyParams {
302
+ return self.royalty_params!!;
303
+ }
304
+ }
@@ -0,0 +1,102 @@
1
+ import "@stdlib/deploy";
2
+ import "./simple_nft_collection_v2";
3
+ import "./message.tact";
4
+
5
+ contract SimpleNftMaster with Deployable {
6
+
7
+ /*
8
+ Root contract of SimpleNFT project
9
+ Powered by Vorpal team
10
+ https://github.com/VORPALTEAM
11
+
12
+ Code by Yuriy Berland
13
+ https://github.com/YuriyBum
14
+ */
15
+
16
+ owner: Address;
17
+ next_collection_index: Int = 0;
18
+ collection_creation_price: Int as uint32 = 0;
19
+
20
+ init(
21
+ owner: Address,
22
+ creation_price: Int,
23
+ ) {
24
+ self.owner = owner;
25
+ self.collection_creation_price = creation_price;
26
+ }
27
+
28
+ receive(msg: CollectionMintParams) {
29
+ require(self.next_collection_index >= 0, "non-sequential Collections");
30
+ let ctx: Context = context();
31
+ require(ctx.value >= self.collection_creation_price, "Creation underpriced");
32
+ let minPriceRequired = msg.enable_profile ? nftBalanceConst : minPriceNoProfile;
33
+ require(msg.nft_price >= minPriceRequired, "Token price too low");
34
+ if (msg.mint_time_limit > 0) {
35
+ require(msg.mint_time_limit > now(), "Collection must have time to mint");
36
+ }
37
+ let collection_init: StateInit = self.getCollectionItemInit(self.next_collection_index);
38
+
39
+ send(SendParameters{
40
+ to: contractAddress(collection_init),
41
+ value: masterMinStorage,
42
+ bounce: false,
43
+ mode: SendIgnoreErrors,
44
+ body: CollectionSetupParams {
45
+ owner_address: msg.owner_address,
46
+ master_address: myAddress(),
47
+ collection_content: msg.collection_content,
48
+ nft_individual_content_url: msg.nft_individual_content_url,
49
+ royalty_params: msg.royalty_params,
50
+ mint_limit: msg.mint_limit,
51
+ nft_price: msg.nft_price,
52
+ mint_time_limit: msg.mint_time_limit,
53
+ is_sbt: msg.is_sbt,
54
+ enable_whitelist: msg.enable_whitelist,
55
+ enable_profile: msg.enable_profile,
56
+ user_item_limit: msg.user_item_limit
57
+ }.toCell(),
58
+ code: collection_init.code,
59
+ data: collection_init.data
60
+ });
61
+ self.next_collection_index = self.next_collection_index + 1;
62
+ }
63
+
64
+ receive(msg: Withdraw) {
65
+ require(sender() == self.owner, "Not from owner");
66
+ send(SendParameters{
67
+ to: msg.to,
68
+ value: myBalance() - masterMinStorage,
69
+ bounce: false,
70
+ mode: SendIgnoreErrors
71
+ });
72
+ }
73
+
74
+ receive(msg: TransferOwner) {
75
+ require(sender() == self.owner, "Not from owner");
76
+ self.owner = msg.new_owner;
77
+ }
78
+
79
+ receive() {}
80
+
81
+ get fun getCollectionItemInit(item_index: Int): StateInit {
82
+ return initOf SimpleNftCollectionV2(myAddress(), item_index);
83
+ }
84
+
85
+ get fun get_master_data (): MasterData {
86
+ return MasterData{
87
+ master: self.owner,
88
+ next_collection_index: self.next_collection_index,
89
+ collection_creation_price: self.collection_creation_price
90
+ }
91
+ }
92
+
93
+ get fun get_collection_address_by_index (collection_index: Int): Address? {
94
+ let initCode: StateInit = self.getCollectionItemInit(collection_index);
95
+ return contractAddress(initCode);
96
+ }
97
+
98
+ get fun get_next_collection_index (): Int {
99
+ return self.next_collection_index;
100
+ }
101
+
102
+ }
package/dist/api.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import type { ProjectServerResult } from './backend-types';
2
+ export declare class ProjectServerError extends Error {
3
+ readonly url: string;
4
+ readonly status?: number;
5
+ constructor(url: string, message: string, status?: number);
6
+ }
7
+ export declare function normalizeHostname(hostname: string): string;
8
+ export declare function buildUrl(hostname: string, path: string): string;
9
+ export declare function getJson<T>(url: string): Promise<T>;
10
+ export declare function getJsonResult<T>(url: string): Promise<ProjectServerResult<T>>;
package/dist/api.js ADDED
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProjectServerError = void 0;
4
+ exports.normalizeHostname = normalizeHostname;
5
+ exports.buildUrl = buildUrl;
6
+ exports.getJson = getJson;
7
+ exports.getJsonResult = getJsonResult;
8
+ class ProjectServerError extends Error {
9
+ constructor(url, message, status) {
10
+ super(message);
11
+ this.name = 'ProjectServerError';
12
+ this.url = url;
13
+ this.status = status;
14
+ }
15
+ }
16
+ exports.ProjectServerError = ProjectServerError;
17
+ function normalizeHostname(hostname) {
18
+ return hostname.replace(/\/+$/, '');
19
+ }
20
+ function buildUrl(hostname, path) {
21
+ const normalizedHost = normalizeHostname(hostname);
22
+ const normalizedPath = path.startsWith('/') ? path : `/${path}`;
23
+ return `${normalizedHost}${normalizedPath}`;
24
+ }
25
+ async function getJson(url) {
26
+ const response = await fetch(url, {
27
+ method: 'GET',
28
+ headers: {
29
+ Accept: 'application/json',
30
+ },
31
+ });
32
+ if (!response.ok) {
33
+ throw new ProjectServerError(url, response.statusText || `HTTP ${response.status}`, response.status);
34
+ }
35
+ return (await response.json());
36
+ }
37
+ async function getJsonResult(url) {
38
+ try {
39
+ const data = await getJson(url);
40
+ return {
41
+ ok: true,
42
+ status: 'ok',
43
+ url,
44
+ data,
45
+ };
46
+ }
47
+ catch (error) {
48
+ const serverError = error instanceof ProjectServerError ? error : undefined;
49
+ const httpStatus = serverError?.status;
50
+ return {
51
+ ok: false,
52
+ status: httpStatus === 404 ? 'not_found' : 'request_failed',
53
+ url,
54
+ error: error instanceof Error ? error.message : String(error),
55
+ httpStatus,
56
+ };
57
+ }
58
+ }
@@ -0,0 +1,13 @@
1
+ import { Address } from '@ton/core';
2
+ import type { ProjectCollectionData, ProjectItemData, ProjectServerResult } from './backend-types';
3
+ export interface ProjectServerPaths {
4
+ collectionData?: (address: string) => string;
5
+ itemData?: (address: string) => string;
6
+ }
7
+ export declare class ProjectBackendService {
8
+ readonly hostname: string;
9
+ private readonly paths;
10
+ constructor(hostname: string, paths?: ProjectServerPaths);
11
+ collectionData(address: string | Address): Promise<ProjectServerResult<ProjectCollectionData>>;
12
+ itemData(address: string | Address): Promise<ProjectServerResult<ProjectItemData>>;
13
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProjectBackendService = void 0;
4
+ const api_1 = require("./api");
5
+ const defaultPaths = {
6
+ collectionData: (address) => `/api/collection/${address}`,
7
+ itemData: (address) => `/api/item/${address}`,
8
+ };
9
+ function stringifyAddress(address) {
10
+ return typeof address === 'string' ? address : address.toString();
11
+ }
12
+ class ProjectBackendService {
13
+ constructor(hostname, paths = {}) {
14
+ this.hostname = hostname;
15
+ this.paths = {
16
+ ...defaultPaths,
17
+ ...paths,
18
+ };
19
+ }
20
+ collectionData(address) {
21
+ const stringAddress = stringifyAddress(address);
22
+ return (0, api_1.getJsonResult)((0, api_1.buildUrl)(this.hostname, this.paths.collectionData(stringAddress)));
23
+ }
24
+ itemData(address) {
25
+ const stringAddress = stringifyAddress(address);
26
+ return (0, api_1.getJsonResult)((0, api_1.buildUrl)(this.hostname, this.paths.itemData(stringAddress)));
27
+ }
28
+ }
29
+ exports.ProjectBackendService = ProjectBackendService;
@@ -0,0 +1,60 @@
1
+ export interface CollectionFileData {
2
+ name: string;
3
+ description: string;
4
+ social_links: string[];
5
+ imageUrl: string;
6
+ backgroundUrl: string;
7
+ }
8
+ export interface Attribute {
9
+ trait_type: string;
10
+ value: string;
11
+ }
12
+ export interface ItemFileData {
13
+ name?: string;
14
+ description?: string;
15
+ marketplace?: string;
16
+ image: string;
17
+ attributes: Attribute[];
18
+ content_type?: string;
19
+ content_url?: string;
20
+ }
21
+ export interface ProjectCollectionData {
22
+ owner: string;
23
+ address: string;
24
+ mint_limit: number;
25
+ price: number;
26
+ next_item_index?: number;
27
+ next_item_address?: string;
28
+ data_url: string;
29
+ item_data_url?: string;
30
+ is_sbt?: boolean;
31
+ mint_time_limit?: number;
32
+ is_hidden_by_owner?: boolean;
33
+ enable_whitelist?: boolean | null;
34
+ user_item_limit?: number;
35
+ stars?: number;
36
+ volume?: number;
37
+ experience?: number;
38
+ }
39
+ export interface ProjectItemData {
40
+ address: string;
41
+ collection: string;
42
+ data_url: string;
43
+ index_in_collection: string;
44
+ minter?: string;
45
+ metadata?: ItemFileData;
46
+ }
47
+ export type ProjectServerStatus = 'ok' | 'not_found' | 'request_failed' | 'invalid_response';
48
+ export type ProjectServerResult<T> = {
49
+ ok: true;
50
+ status: 'ok';
51
+ url: string;
52
+ data: T;
53
+ } | {
54
+ ok: false;
55
+ status: Exclude<ProjectServerStatus, 'ok'>;
56
+ url: string;
57
+ error: string;
58
+ httpStatus?: number;
59
+ };
60
+ export type DeploymentStatus = 'deployed_with_server_data' | 'deployed_server_data_unavailable' | 'deployment_not_confirmed';
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ import { Cell } from '@ton/core';
2
+ export declare function encodeOffchainContent(content: string): Cell;
3
+ export declare function normalizeContent(content: string | Cell): Cell;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.encodeOffchainContent = encodeOffchainContent;
4
+ exports.normalizeContent = normalizeContent;
5
+ const core_1 = require("@ton/core");
6
+ const OFFCHAIN_CONTENT_PREFIX = 0x01;
7
+ function bufferToChunks(buffer, chunkSize) {
8
+ const chunks = [];
9
+ let remaining = buffer;
10
+ while (remaining.byteLength > 0) {
11
+ chunks.push(remaining.subarray(0, chunkSize));
12
+ remaining = remaining.subarray(chunkSize);
13
+ }
14
+ return chunks;
15
+ }
16
+ function encodeOffchainContent(content) {
17
+ const data = Buffer.concat([Buffer.from([OFFCHAIN_CONTENT_PREFIX]), Buffer.from(content)]);
18
+ const chunks = bufferToChunks(data, 127);
19
+ if (chunks.length === 0) {
20
+ return (0, core_1.beginCell)().endCell();
21
+ }
22
+ let current = (0, core_1.beginCell)().storeBuffer(chunks[chunks.length - 1]).endCell();
23
+ for (let i = chunks.length - 2; i >= 0; i -= 1) {
24
+ current = (0, core_1.beginCell)().storeBuffer(chunks[i]).storeRef(current).endCell();
25
+ }
26
+ return current;
27
+ }
28
+ function normalizeContent(content) {
29
+ return typeof content === 'string' ? encodeOffchainContent(content) : content;
30
+ }