diff --git a/bin/api.js b/bin/api.js index bf631c9..42592de 100644 --- a/bin/api.js +++ b/bin/api.js @@ -5,6 +5,8 @@ const {Base64} = require('@tonconnect/protocol'); const express = require('express') const {get_tonclient, AdnlAddress} = require("../contracts/utils"); const {getRecords} = require("../contracts/main"); +const {sha256} = require("ton-crypto"); +const {BN} = require("bn.js"); const app = express() const port = 5171 const debug = process.env.DEBUG === '1'; @@ -41,12 +43,14 @@ app.get('/content-message/:address/:zone/:domain', async (req, res) => { app.get('/address/:collection/:domain', (req, res) => { let addr = main.getItemAddr(Address.parse(req.params.collection), req.params.domain, 0); + console.log(addr.toFriendly()) res.send(JSON.stringify({"address": addr.toString()})); }) app.get('/get-records/:address', async (req, res) => { try { let records = await getRecords(tonclient, Address.parse(req.params.address)); + // console.log(records) res.send(JSON.stringify(records)); } catch (e) { console.log(e); @@ -60,6 +64,10 @@ app.get('/set-record/site/:site', async (req, res) => { res.send(JSON.stringify(Base64.encode(msg.toBoc()))); }) +app.get('/hash/:key', async (req, res) => { + res.send(new BN(await sha256(req.params.key)).toString()); +}) + app.get('/set-record/wallet/:wallet', async (req, res) => { let wallet = Address.parse(req.params.wallet); let msg = await main.changeRecordMsg("wallet", await main.WalletRecord(wallet)); diff --git a/build/nft-collection.deploy.ts b/build/nft-collection.deploy.ts index e3f0973..b3f9c59 100644 --- a/build/nft-collection.deploy.ts +++ b/build/nft-collection.deploy.ts @@ -7,9 +7,11 @@ import BN from "bn.js"; // return the init Cell of the contract storage (according to load_data() contract method) export function initData() { + let isTestnet = false; return main.collectionData({ - ownerAddress: Address.parseFriendly("kQBw4_jZTQVbOSDbUjAMibTHWbstrCqjOnzvUTCphGpTFDrK").address, + ownerAddress: Address.parseFriendly("EQB_hLB81P0BuBqcitfwoLRd2QX4l4SY-w2fWob9xdWNQgSx").address, code: Cell.fromBoc(item_code)[0], + zone: isTestnet ? "example.ton" : "nftcoffee.ton", ownerKey: new BN(0) // 63181357919630091755807889549433422416741950993093777020964723182484811889834 }); } diff --git a/contracts/imports/dns-utils.fc b/contracts/imports/dns-utils.fc index cffc9b0..420a117 100644 --- a/contracts/imports/dns-utils.fc +++ b/contracts/imports/dns-utils.fc @@ -173,35 +173,35 @@ int check_domain_string(slice domain) { return (10, 1); } -int price_function(int length, int multiplierx10, int steepness) { +int price_function(int length, int multiplierx50, int steepness) { ;; length is the length of the domain, the price depends on it. The rest is the price config - ;; multiplierx10 is the price multiplier, the default price is multiplied by multiplierx10 / 10 + ;; multiplierx50 is the price multiplier, the default price is multiplied by multiplierx50 / 50 ;; steepness (from 0 to 10) is the steepness of the price function, ;; 10 means the distribution is as in the function from `get_min_price_config` (the second number), 0 means the price is always the same, 50 - int price = 50; + int price = 25; if (length == 3) { - price = 200; + price = 100; } if (length == 4) { - price = 100; + price = 50; } if (length == 5) { - price = 50; + price = 25; } if (length == 6) { - price = 40; + price = 20; } if (length == 7) { - price = 30; + price = 15; } if (length == 8) { - price = 20; + price = 10; } if (length >= 9) { - price = 10; + price = 5; } - price = (steepness * price + (10 - steepness) * 50) / 50; - return price * one_ton * multiplierx10 / 10; + price = (steepness * price + (10 - steepness) * 25) / 10; + return price * one_ton * multiplierx50 / 50; } int get_min_price(int domain_bits_length, int now_time) { diff --git a/contracts/main.ts b/contracts/main.ts index 9968be3..0050ed8 100644 --- a/contracts/main.ts +++ b/contracts/main.ts @@ -46,6 +46,10 @@ export function data(params: { ownerAddress: Address; collectionAddress: Address return beginCell().storeRef(data_cell).storeBuffer(params.publicKey).endCell(); } +function strCell(str: string): Cell { + return beginCell().storeBuffer(Buffer.from(str)).endCell(); +} + export function collectionData(params: { code: Cell, ownerAddress: Address, ownerKey: BN, price_multiplier?: number, price_steepness?: number, zone?: string @@ -54,10 +58,10 @@ export function collectionData(params: { params.price_multiplier = 1; } if (params.price_steepness == undefined) { - params.price_steepness = 1; + params.price_steepness = 0; } if (params.zone == undefined) { - params.zone = "example"; + params.zone = "example.ton"; } return beginCell() .storeRef(encodeOffChainContent(`https://api.agorata.io/data/${params.zone}.json`)) // https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md @@ -67,8 +71,11 @@ export function collectionData(params: { .storeAddress(params.ownerAddress) .storeRef( beginCell() - .storeRef(beginCell().storeBuffer(Buffer.from(`https://api.agorata.io/data/${params.zone}/`)).endCell()) - .storeRef(beginCell().storeBuffer(Buffer.from(`.json`)).endCell()) + .storeRef(strCell(`https://api.agorata.io/data/${params.zone}/`)) + .storeRef(beginCell().storeRef(strCell(`.json`)) + .storeRef(strCell(`.png`)).endCell()) + .storeRef(strCell('.' + params.zone)) + .storeRef(strCell(`A TON DNS domain in the ${params.zone} zone. By agorata.io`)) .endCell()) .endCell(); } @@ -120,9 +127,10 @@ export async function getRecords(tonclient: TonClient, address: Address) { // print site_data converted from base64 let c = Cell.fromBoc(Buffer.from(site_data, 'base64'))[0].beginParse(); c.skip(16); - site = new AdnlAddress(c.readRemainingBytes().subarray(2, 2 + 32)).toHex(); + site = new AdnlAddress(c.readRemainingBytes().subarray(0, 32)).toHex(); } } catch (e) { + console.log(e) } let uri = null; try { @@ -131,9 +139,12 @@ export async function getRecords(tonclient: TonClient, address: Address) { ["num", new BN(await sha256('uri')).toString()]])).stack[1]; uri = Cell.fromBoc(Buffer.from(ans_uri[1].bytes, "base64"))[0].beginParse().readRemainingBytes().toString(); } catch (e) { - console.log(e); - console.log((await tonclient.callGetMethod(address, 'get_nft_data')).stack[4]); + // console.log((await tonclient.callGetMethod(address, 'get_nft_data')).stack[4]); } + // let name_uri = (await tonclient.callGetMethod(address, 'dnsresolve', + // [["tvm.Slice", "te6cckEBAQEAAwAAAgDTZ9xB"], + // ["num", new BN(await sha256('image')).toString()]])).stack[1]; + // console.log(Cell.fromBoc(Buffer.from(name_uri[1].bytes, "base64"))[0].beginParse().readRemainingBytes().toString()); return {wallet, site, uri}; } @@ -237,7 +248,13 @@ export function initializeItemMsg(params: { domain: String, ownerAddr: Address, return beginCell() .storeAddress(params.ownerAddr) .storeRef(beginCell().storeBuffer(Buffer.from(params.domain)).endCell()) - .storeRef(beginCell().storeBuffer(Buffer.from(`https://api.agorata.io/data/${params.zone}/${params.domain}.json`)).endCell()) + .storeRef(beginCell() + .storeRef(strCell(`https://api.agorata.io/data/${params.zone}/${params.domain}.json`)) + .storeRef(strCell(`https://api.agorata.io/data/${params.zone}/${params.domain}.png`)) + .storeRef(strCell(`${params.zone}.${params.domain}`)) + .storeRef(strCell(`A TON DNS domain in the ${params.zone} zone`)) + .endCell() + ) .endCell(); } @@ -254,11 +271,6 @@ export async function setContent(params: { domain: string, zone: string }) { return changeRecordMsg("uri", beginCell().storeBuffer(Buffer.from(`https://api.agorata.io/data/${params.zone}/${params.domain}.json`)).endCell()); } -export function loadRecords(map_cell: Cell) { - let map_sl = map_cell.beginParse(); - map_sl -} - export function instantBuySignature(receiverAddress: Address, issuedCollectionAddr: Address, amount: number, domain: Cell, privateKey: Buffer): Buffer { let messageToSign = beginCell().storeAddress(receiverAddress).storeAddress(issuedCollectionAddr).storeUint(amount, 256).storeRef(domain).endCell(); let hash = messageToSign.hash(); diff --git a/contracts/nft-collection.fc b/contracts/nft-collection.fc index c163143..2f2d949 100644 --- a/contracts/nft-collection.fc +++ b/contracts/nft-collection.fc @@ -10,7 +10,11 @@ ;; cell pricing ;; uint256(key) owner_key ;; address owner_address -;; cell uri_scheme: prefix slice as a cell, then postfix ('.json') slice as a cell +;; cell data_scheme: +;; uri prefix for image and data slice as a cell +;; cell: uri postfix ('.json') slice as a cell, image uri postfix ('.png') +;; zone +;; description (cell, cell, cell, int, slice, cell) load_data() inline { var ds = get_data().begin_parse(); @@ -20,18 +24,18 @@ ds~load_ref(), ;; pricing ds~load_uint(256), ;; owner key ds~load_msg_addr(), ;; owner address - ds~load_ref() ;; uri_scheme + ds~load_ref() ;; data_scheme ); } -() save_data(cell content, cell nft_item_code, cell pricing, int owner_key, slice owner_addr, cell uri_scheme) impure inline { +() save_data(cell content, cell nft_item_code, cell pricing, int owner_key, slice owner_addr, cell data_scheme) impure inline { set_data(begin_cell() .store_ref(content) .store_ref(nft_item_code) .store_ref(pricing) .store_uint(owner_key, 256) .store_slice(owner_addr) - .store_ref(uri_scheme) + .store_ref(data_scheme) .end_cell()); } @@ -53,13 +57,26 @@ cell calculate_nft_item_state_init(int item_index, cell nft_item_code) { return begin_cell().store_uint(0, 2).store_dict(nft_item_code).store_dict(data).store_uint(0, 1).end_cell(); } -cell get_uri(slice domain, cell uri_scheme) { - ;; parse the prefix and the postfix out of uri_scheme - slice cs = uri_scheme.begin_parse(); +cell get_attachment(slice domain, cell data_scheme) { + ;; parse the prefix and the postfix out of data_scheme + slice cs = data_scheme.begin_parse(); slice prefix = cs~load_ref().begin_parse(); - slice postfix = cs~load_ref().begin_parse(); + slice postfixes = cs~load_ref().begin_parse(); + slice postfix = postfixes~load_ref().begin_parse(); + slice image_postfix = postfixes~load_ref().begin_parse(); ;; create the slice with the uri: prefix + domain + postfix - return begin_cell().store_slice(prefix).store_slice(domain).store_slice(postfix).end_cell(); + cell uri_cell = begin_cell().store_uint(1, 8).store_slice(prefix).store_slice(domain).store_slice(postfix).end_cell(); + cell image_uri_cell = begin_cell().store_slice(prefix).store_slice(domain).store_slice(image_postfix).end_cell(); + slice zone = cs~load_ref().begin_parse(); + cell name_cell = begin_cell().store_slice(domain).store_slice(zone).end_cell(); + cell desc_cell = cs~load_ref(); + cell full_cell = begin_cell() + .store_ref(uri_cell) + .store_ref(image_uri_cell) + .store_ref(name_cell) + .store_ref(desc_cell) + .end_cell(); + return full_cell; } slice calculate_nft_item_address(int wc, cell state_init) { @@ -119,7 +136,7 @@ int verify_signature(slice signature, slice sender_address, slice domain, int ow int op = in_msg_body~load_uint(32); - var (content, nft_item_code, pricing, key, addr, uri_scheme) = load_data(); + var (content, nft_item_code, pricing, key, addr, data_scheme) = load_data(); if (op == 0) { ;; deploy new nft int now_time = now(); @@ -140,7 +157,7 @@ int verify_signature(slice signature, slice sender_address, slice domain, int ow cell nft_content = begin_cell() .store_slice(sender_address) .store_ref(begin_cell().store_slice(domain).end_cell()) - .store_ref(get_uri(domain, uri_scheme)) + .store_ref(get_attachment(domain, data_scheme)) .end_cell(); deploy_nft_item(item_index, nft_item_code, nft_content); return (); @@ -162,12 +179,12 @@ int verify_signature(slice signature, slice sender_address, slice domain, int ow ;; Get methods (int, cell, slice) get_collection_data() method_id { - var (content, nft_item_code, pricing, key, addr, uri_scheme) = load_data(); + var (content, nft_item_code, pricing, key, addr, data_scheme) = load_data(); return (-1, content, zero_address()); } slice get_nft_address_by_index(int index) method_id { - var (content, nft_item_code, pricing, key, addr, uri_scheme) = load_data(); + var (content, nft_item_code, pricing, key, addr, data_scheme) = load_data(); cell state_init = calculate_nft_item_state_init(index, nft_item_code); return calculate_nft_item_address(workchain(), state_init); } @@ -177,7 +194,7 @@ cell get_nft_content(int index, cell individual_nft_content) method_id { } int get_price(slice domain) method_id { - var (content, nft_item_code, pricing, key, addr, uri_scheme) = load_data(); + var (content, nft_item_code, pricing, key, addr, data_scheme) = load_data(); return calcprice(domain, pricing); } diff --git a/contracts/nft-item.fc b/contracts/nft-item.fc index 280ddf8..db5e0b6 100644 --- a/contracts/nft-item.fc +++ b/contracts/nft-item.fc @@ -3,10 +3,13 @@ #include "imports/op-codes.fc"; #include "imports/params.fc"; -int min_tons_for_storage() asm "1000000000 PUSHINT"; ;; 1 TON +int min_tons_for_storage() asm "500000000 PUSHINT"; ;; 0.5 TON ;; sha256('uri') const uri_key = 51065135818459385347574250312853146822620586594996463797054414300406918686668; +const name_key = 59089242681608890680090686026688704441792375738894456860693970539822503415433; +const image_key = 43884663033947008978309661017057008345326326811558777475113826163084742639165; +const description_key = 90922719342317012409671596374183159143637506542604000676488204638996496437508; ;; ;; === Storage === @@ -15,26 +18,28 @@ const uri_key = 5106513581845938534757425031285314682262058659499646379705441430 ;; MsgAddressInt collection_address ;; MsgAddressInt owner_address ;; cell content +;; cell uri ;; cell domain - e.g contains "alice" (without ending \0) for "alice.ton" domain ;; int last_fill_up_time -(int, int, slice, slice, cell, cell, int) load_data() { +(int, int, slice, slice, cell, cell, cell, int) load_data() { slice ds = get_data().begin_parse(); var (index, collection_address) = (ds~load_uint(256), ds~load_msg_addr()); if (ds.slice_bits() > 0) { - return (-1, index, collection_address, ds~load_msg_addr(), ds~load_ref(), ds~load_ref(), ds~load_uint(64)); + return (-1, index, collection_address, ds~load_msg_addr(), ds~load_ref(), ds~load_ref(), ds~load_ref(), ds~load_uint(64)); } else { - return (0, index, collection_address, null(), null(), null(), 0); ;; nft not initialized yet + return (0, index, collection_address, null(), null(), null(), null(), 0); ;; nft not initialized yet } } -() store_data(int index, slice collection_address, slice owner_address, cell content, cell domain, int last_fill_up_time) impure { +() store_data(int index, slice collection_address, slice owner_address, cell content, cell uri, cell domain, int last_fill_up_time) impure { set_data( begin_cell() .store_uint(index, 256) .store_slice(collection_address) .store_slice(owner_address) .store_ref(content) + .store_ref(uri) .store_ref(domain) .store_uint(last_fill_up_time, 64) .end_cell() @@ -57,7 +62,7 @@ const uri_key = 5106513581845938534757425031285314682262058659499646379705441430 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, cell domain) impure inline { +() transfer_ownership(int my_balance, int index, slice collection_address, slice owner_address, cell content, cell uri, slice sender_address, int query_id, slice in_msg_body, int fwd_fees, cell domain) impure inline { slice new_owner_address = in_msg_body~load_msg_addr(); force_chain(new_owner_address); slice response_destination = in_msg_body~load_msg_addr(); @@ -83,7 +88,7 @@ const uri_key = 5106513581845938534757425031285314682262058659499646379705441430 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, domain, now()); + store_data(index, collection_address, new_owner_address, content, uri, domain, now()); } () recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure { @@ -102,16 +107,27 @@ const uri_key = 5106513581845938534757425031285314682262058659499646379705441430 cs~load_coins(); ;; skip ihr_fee int fwd_fee = cs~load_coins(); ;; we use message fwd_fee for estimation of forward_payload costs - (int init?, int index, slice collection_address, slice owner_address, cell content, cell domain, int last_fill_up_time) = load_data(); + (int init?, int index, slice collection_address, slice owner_address, cell content, cell uri, cell domain, int last_fill_up_time) = load_data(); if (~ init?) { throw_unless(405, equal_slices(collection_address, sender_address)); slice from_address = in_msg_body~load_msg_addr(); cell domain = in_msg_body~load_ref(); - cell uri = in_msg_body~load_ref(); + slice attachment = in_msg_body~load_ref().begin_parse(); + cell uri = attachment~load_ref(); + cell img_uri = attachment~load_ref(); + cell name = attachment~load_ref(); + cell description = attachment~load_ref(); cell content_dict = new_dict(); - content_dict~udict_set_ref(256, uri_key, uri); +;; content_dict~udict_set_ref(256, uri_key, uri); + content_dict~udict_set_ref(256, image_key, img_uri); + content_dict~udict_set_ref(256, name_key, name); + content_dict~udict_set_ref(256, description_key, description); cell content = begin_cell().store_uint(0, 8).store_dict(content_dict).end_cell(); - store_data(index, collection_address, from_address, content, domain, now()); + store_data(index, collection_address, from_address, content, uri, domain, now()); + int rest_amount = msg_value - fwd_fee - min_tons_for_storage(); + if (rest_amount > 0) { + send_msg(collection_address, rest_amount, op::excesses(), 0, null(), 1); ;; paying fees, revert on errors + } return (); } @@ -125,7 +141,7 @@ const uri_key = 5106513581845938534757425031285314682262058659499646379705441430 if (op == 0) { - store_data(index, collection_address, owner_address, content, domain, now()); + store_data(index, collection_address, owner_address, content, uri, domain, now()); return (); } @@ -134,12 +150,12 @@ const uri_key = 5106513581845938534757425031285314682262058659499646379705441430 if (op == op::transfer()) { throw_unless(401, equal_slices(sender_address, owner_address)); - transfer_ownership(my_balance, index, collection_address, owner_address, content, sender_address, query_id, in_msg_body, fwd_fee, domain); + transfer_ownership(my_balance, index, collection_address, owner_address, content, uri, sender_address, query_id, in_msg_body, fwd_fee, domain); return (); } if (op == op::edit_content()) { ;; owner can change content and dns records throw_unless(410, equal_slices(sender_address, owner_address)); - store_data(index, collection_address, owner_address, in_msg_body~load_ref(), domain, now()); + store_data(index, collection_address, owner_address, in_msg_body~load_ref(), in_msg_body~load_ref(), domain, now()); return (); } if (op == op::change_dns_record) { ;; change dns record @@ -161,7 +177,7 @@ const uri_key = 5106513581845938534757425031285314682262058659499646379705441430 content = begin_cell().store_uint(0, 8).store_dict(keyvalue_map).end_cell(); - store_data(index, collection_address, owner_address, content, domain, now()); + store_data(index, collection_address, owner_address, content, uri, domain, now()); return (); } if (op == op::process_governance_decision) { ;; governance @@ -172,7 +188,7 @@ const uri_key = 5106513581845938534757425031285314682262058659499646379705441430 int config_op = config_value~load_uint(8); throw_unless(416, (config_op == 0) | (config_op == 1)); if (config_op == 0) { ;; transfer - transfer_ownership(my_balance, index, collection_address, owner_address, content, sender_address, query_id, config_value, fwd_fee, domain); + transfer_ownership(my_balance, index, collection_address, owner_address, content, uri, sender_address, query_id, config_value, fwd_fee, domain); } if (config_op == 1) { ;; destroy send_msg(collection_address, 0, op::fill_up, query_id, null(), 128 + 32); ;; carry all the remaining balance + destroy @@ -191,22 +207,22 @@ const uri_key = 5106513581845938534757425031285314682262058659499646379705441430 ;; (int, int, slice, slice, cell) get_nft_data() method_id { - (int init?, int index, slice collection_address, slice owner_address, cell content, cell domain, int last_fill_up_time) = load_data(); - return (init?, index, collection_address, owner_address, content); + (int init?, int index, slice collection_address, slice owner_address, cell content, cell uri, cell domain, int last_fill_up_time) = load_data(); + return (init?, index, collection_address, owner_address, uri); } slice get_editor() method_id { - (int init?, int index, slice collection_address, slice owner_address, cell content, cell domain, int last_fill_up_time) = load_data(); + (int init?, int index, slice collection_address, slice owner_address, cell content, cell uri, cell domain, int last_fill_up_time) = load_data(); return owner_address; } slice get_domain() method_id { - (int init?, int index, slice collection_address, slice owner_address, cell content, cell domain, int last_fill_up_time) = load_data(); + (int init?, int index, slice collection_address, slice owner_address, cell content, cell uri, cell domain, int last_fill_up_time) = load_data(); return domain.begin_parse(); } int get_last_fill_up_time() method_id { - (int init?, int index, slice collection_address, slice owner_address, cell content, cell domain, int last_fill_up_time) = load_data(); + (int init?, int index, slice collection_address, slice owner_address, cell content, cell uri, cell domain, int last_fill_up_time) = load_data(); return last_fill_up_time; } @@ -215,7 +231,7 @@ int get_last_fill_up_time() method_id { throw_unless(70, mod(subdomain_bits, 8) == 0); - (int init?, int index, slice collection_address, slice owner_address, cell content, cell my_domain_cell, int last_fill_up_time) = load_data(); + (int init?, int index, slice collection_address, slice owner_address, cell content, cell uri, cell domain, int last_fill_up_time) = load_data(); slice cs = content.begin_parse(); throw_unless(412, cs~load_uint(8) == 0); ;; data onchain tag diff --git a/test/item.spec.ts b/test/item.spec.ts index fac662f..672deb3 100644 --- a/test/item.spec.ts +++ b/test/item.spec.ts @@ -4,7 +4,7 @@ import BN from "bn.js"; chai.use(chaiBN(BN)); -import {Address, beginCell, Builder, Cell, contractAddress, parseDict, parseDictBitString, Slice} from "ton"; +import {Address, beginCell, Builder, Cell, contractAddress, parseDict, parseDictBitString, Slice, toNano} from "ton"; import {runContract, SmartContract} from "ton-contract-executor"; import * as main from "../contracts/main"; import {internalMessage, randomAddress} from "./helpers"; @@ -17,7 +17,7 @@ import {Base64} from "@tonconnect/protocol"; let data = main.itemDataUninit({domain: "test", collectionAddress: randomAddress("collection")}); -describe("Creating items tests", () => { +describe("Creating item tests", () => { let contract: SmartContract; let debug: boolean = true; @@ -28,7 +28,8 @@ describe("Creating items tests", () => { {debug: debug} ); contract.setC7Config({ - myself: randomAddress("item") + myself: randomAddress("item"), + balance: toNano(1).toNumber(), }) }); @@ -48,7 +49,7 @@ describe("Creating items tests", () => { const setDataMsg = internalMessage({ from: ownerAddr, body: await main.setContent({domain: "levcccc", zone: "example.ton"}), - value: new BN(0), + value: new BN(toNano(2)), }) const res2 = await contract.sendInternalMessage(setDataMsg); expect(res2.type).to.equal("success"); diff --git a/test/signing.spec.ts b/test/signing.spec.ts index 20b28e1..4c327d1 100644 --- a/test/signing.spec.ts +++ b/test/signing.spec.ts @@ -23,7 +23,7 @@ let data = main.collectionData({ ownerKey: ownerPubNum, }); -describe("Creating items tests", () => { +describe("Signing tests", () => { let contract: SmartContract; let debug: boolean = true;