diff --git a/bin/cli.js b/bin/cli.js index 29564e2..3ec92f4 100644 --- a/bin/cli.js +++ b/bin/cli.js @@ -1,13 +1,15 @@ const main = require('../contracts/main'); const subcommand = require('subcommand'); const {Address} = require("ton"); -const {keyPairFromSeed, getSecureRandomBytes} = require("ton-crypto"); +const {keyPairFromSeed, getSecureRandomBytes, keyPairFromSecretKey} = require("ton-crypto"); +const {Base64} = require('@tonconnect/protocol'); +const BN = require("bn.js"); const argv = process.argv.slice(2); let commands = [ { - name: 'sign-message', + name: 'buy-message', options: [ // cliclopts options // { // name: 'loud', @@ -31,12 +33,18 @@ let commands = [ help: 'Secret key, hex-encoded' } ], - command: function sign_message(args) { - let key = Buffer.from(args.key, 'hex'); - let collection = Address.parse(args.collection); - let buyer = Address.parse(args.buyer); - let signature = main.signBuy(args.domain, collection, buyer, key); - console.log(signature); + command: function message(args) { + let collection = Address.parse(args._[1]); + if (args._[2] !== '') { + let buyer = Address.parse(args._[2]); + let key = Buffer.from(args._[3], 'hex'); + let signature = main.signBuy(args._[0], collection, buyer, key); + let msg = main.createItem({domain: args._[0], signature}) + console.log(Base64.encode(msg.toBoc()) + ' ' + collection.toString()); + } else { + let msg = main.createItem({domain: args._[0], signature: '0'}) + console.log(Base64.encode(msg.toBoc()) + ' ' + collection.toString()); + } } }, { @@ -45,6 +53,45 @@ let commands = [ let keypair = keyPairFromSeed(await getSecureRandomBytes(32)); console.log(keypair.secretKey.toString('hex')); } + }, + { + name: 'getpub', // get public key as BN from b64 secret key + options: [ + { + name: 'key', + help: 'Secret key, hex-encoded' + } + ], + command: function getpub(args) { + let keypair = keyPairFromSecretKey(Buffer.from(args._[0], 'base64')); + console.log(new BN(keypair.publicKey)) + } + }, + { + name: 'content-message', + options: [ + { + name: 'domain', + help: 'domain name to set content for (test for test.example.ton)' + }, + { + name: 'zone', + help: 'zone name to set content for (example.ton for test.example.ton)' + }, + { + name: 'address', + help: 'address of the collection contract' + }, + { + name: 'workchain', + help: '0 for mainnet, 1 for testnet' + } + ], + command: function set_content(args) { + let msg = main.setContent({domain: args._[0], zone: args._[1]}); + let addr = main.getItemAddr(Address.parse(args._[2]), args._[0], args._[3] === '1' ? -1 : 0); + console.log(Base64.encode(msg.toBoc()) + ' ' + addr.toString()); + } } ] diff --git a/build/_build.ts b/build/_build.ts index 7e745f0..37569dd 100644 --- a/build/_build.ts +++ b/build/_build.ts @@ -19,10 +19,10 @@ async function main() { console.log("Build script running, let's find some FunC contracts to compile.."); // if we have an explicit bin directory, use the executables there (needed for glitch.com) - if (fs.existsSync("bin")) { - process.env.PATH = path.join(__dirname, "..", "bin") + path.delimiter + process.env.PATH; - process.env.FIFTPATH = path.join(__dirname, "..", "bin", "fiftlib"); - } + // if (fs.existsSync("bin")) { + // process.env.PATH = path.join(__dirname, "..", "bin") + path.delimiter + process.env.PATH; + // process.env.FIFTPATH = path.join(__dirname, "..", "bin", "fiftlib"); + // } // make sure func compiler is available const minSupportFunc = "0.2.0"; diff --git a/build/_deploy.ts b/build/_deploy.ts index e4f16eb..38348b7 100644 --- a/build/_deploy.ts +++ b/build/_deploy.ts @@ -6,144 +6,152 @@ import axios from "axios"; import axiosThrottle from "axios-request-throttle"; -axiosThrottle.use(axios, { requestsPerSecond: 0.5 }); // required since toncenter jsonRPC limits to 1 req/sec without API key + +axiosThrottle.use(axios, {requestsPerSecond: 0.5}); // required since toncenter jsonRPC limits to 1 req/sec without API key import dotenv from "dotenv"; + dotenv.config(); import fs from "fs"; import path from "path"; import glob from "fast-glob"; -import { Address, Cell, CellMessage, CommonMessageInfo, fromNano, InternalMessage, StateInit, toNano } from "ton"; -import { TonClient, WalletContract, WalletV3R2Source, contractAddress, SendMode } from "ton"; -import { mnemonicNew, mnemonicToWalletKey } from "ton-crypto"; +import {Address, Cell, CellMessage, CommonMessageInfo, fromNano, InternalMessage, StateInit, toNano} from "ton"; +import {TonClient, WalletContract, WalletV3R2Source, contractAddress, SendMode} from "ton"; +import {mnemonicNew, mnemonicToWalletKey} from "ton-crypto"; async function main() { - console.log(`=================================================================`); - console.log(`Deploy script running, let's find some contracts to deploy..`); - - const isTestnet = process.env.TESTNET || process.env.npm_lifecycle_event == "deploy:testnet"; - - // check input arguments (given through environment variables) - if (isTestnet) { - console.log(`\n* We are working with 'testnet' (https://t.me/testgiver_ton_bot will give you test TON)`); - } else { - console.log(`\n* We are working with 'mainnet'`); - } - - // initialize globals - const client = new TonClient({ endpoint: `https://${isTestnet ? "testnet." : ""}toncenter.com/api/v2/jsonRPC` }); - const deployerWalletType = "org.ton.wallets.v3.r2"; // also see WalletV3R2Source class used below - const newContractFunding = toNano(0.02); // this will be (almost in full) the balance of a new deployed contract and allow it to pay rent - const workchain = 0; // normally 0, only special contracts should be deployed to masterchain (-1) - - // make sure we have a wallet mnemonic to deploy from (or create one if not found) - const deployConfigEnv = ".env"; - let deployerMnemonic; - if (!fs.existsSync(deployConfigEnv) || !process.env.DEPLOYER_MNEMONIC) { - console.log(`\n* Config file '${deployConfigEnv}' not found, creating a new wallet for deploy..`); - deployerMnemonic = (await mnemonicNew(24)).join(" "); - const deployWalletEnvContent = `DEPLOYER_WALLET=${deployerWalletType}\nDEPLOYER_MNEMONIC="${deployerMnemonic}"\n`; - fs.writeFileSync(deployConfigEnv, deployWalletEnvContent); - console.log(` - Created new wallet in '${deployConfigEnv}' - keep this file secret!`); - } else { - console.log(`\n* Config file '${deployConfigEnv}' found and will be used for deployment!`); - deployerMnemonic = process.env.DEPLOYER_MNEMONIC; - } - - // open the wallet and make sure it has enough TON - const walletKey = await mnemonicToWalletKey(deployerMnemonic.split(" ")); - const walletContract = WalletContract.create(client, WalletV3R2Source.create({ publicKey: walletKey.publicKey, workchain })); - console.log(` - Wallet address used to deploy from is: ${walletContract.address.toFriendly()}`); - const walletBalance = await client.getBalance(walletContract.address); - if (walletBalance.lt(toNano(0.2))) { - console.log(` - ERROR: Wallet has less than 0.2 TON for gas (${fromNano(walletBalance)} TON), please send some TON for gas first`); - process.exit(1); - } else { - console.log(` - Wallet balance is ${fromNano(walletBalance)} TON, which will be used for gas`); - } - - // go over all the contracts we have deploy scripts for - const rootContracts = glob.sync(["build/*.deploy.ts"]); - for (const rootContract of rootContracts) { - // deploy a new root contract - console.log(`\n* Found root contract '${rootContract} - let's deploy it':`); - const contractName = path.parse(path.parse(rootContract).name).name; - - // prepare the init data cell - const deployInitScript = require(__dirname + "/../" + rootContract); - if (typeof deployInitScript.initData !== "function") { - console.log(` - ERROR: '${rootContract}' does not have 'initData()' function`); - process.exit(1); - } - console.log(1); - const initDataCell = deployInitScript.initData() as Cell; - console.log(2); - - // prepare the init message - if (typeof deployInitScript.initMessage !== "function") { - console.log(` - ERROR: '${rootContract}' does not have 'initMessage()' function`); - process.exit(1); - } - console.log(1); - const initMessageCell = deployInitScript.initMessage() as Cell | null; - - // prepare the init code cell - const hexArtifact = `build/${contractName}.compiled.json`; - if (!fs.existsSync(hexArtifact)) { - console.log(` - ERROR: '${hexArtifact}' not found, did you build?`); - process.exit(1); - } - const initCodeCell = Cell.fromBoc(JSON.parse(fs.readFileSync(hexArtifact).toString()).hex)[0]; - - // make sure the contract was not already deployed - const newContractAddress = contractAddress({ workchain, initialData: initDataCell, initialCode: initCodeCell }); - console.log(` - Based on your init code+data, your new contract address is: ${newContractAddress.toFriendly()}`); - if (await client.isContractDeployed(newContractAddress)) { - console.log(` - Looks like the contract is already deployed in this address, skipping deployment`); - await performPostDeploymentTest(rootContract, deployInitScript, walletContract, walletKey.secretKey, newContractAddress); - continue; + console.log(`=================================================================`); + console.log(`Deploy script running, let's find some contracts to deploy..`); + + const isTestnet = process.env.TESTNET || process.env.npm_lifecycle_event == "deploy:testnet"; + + // check input arguments (given through environment variables) + if (isTestnet) { + console.log(`\n* We are working with 'testnet' (https://t.me/testgiver_ton_bot will give you test TON)`); + } else { + console.log(`\n* We are working with 'mainnet'`); } - // deploy by sending an internal message to the deploying wallet - console.log(` - Let's deploy the contract on-chain..`); - const seqno = await walletContract.getSeqNo(); - const transfer = walletContract.createTransfer({ - secretKey: walletKey.secretKey, - seqno: seqno, - sendMode: SendMode.PAY_GAS_SEPARATLY + SendMode.IGNORE_ERRORS, - order: new InternalMessage({ - to: newContractAddress, - value: newContractFunding, - bounce: false, - body: new CommonMessageInfo({ - stateInit: new StateInit({ data: initDataCell, code: initCodeCell }), - body: initMessageCell !== null ? new CellMessage(initMessageCell) : null, - }), - }), + // initialize globals + const client = new TonClient({ + endpoint: `https://${isTestnet ? "testnet." : ""}toncenter.com/api/v2/jsonRPC`, + apiKey: isTestnet ? 'bed2b4589201ff3c575be653593f912a337c08eed416b60b02345763b9ee9c36' : 'a1e8a1055a387515158589dc7e9bad3035e7db2b9f9ea5cdad6b727f71e328db' }); - await client.sendExternalMessage(walletContract, transfer); - console.log(` - Deploy transaction sent successfully`); - - // make sure that the contract was deployed - console.log(` - Block explorer link: https://${process.env.TESTNET ? "test." : ""}tonwhales.com/explorer/address/${newContractAddress.toFriendly()}`); - console.log(` - Waiting up to 20 seconds to check if the contract was actually deployed..`); - for (let attempt = 0; attempt < 10; attempt++) { - await sleep(2000); - const seqnoAfter = await walletContract.getSeqNo(); - if (seqnoAfter > seqno) break; + const deployerWalletType = "org.ton.wallets.v3.r2"; // also see WalletV3R2Source class used below + const newContractFunding = toNano(0.02); // this will be (almost in full) the balance of a new deployed contract and allow it to pay rent + const workchain = 0; // normally 0, only special contracts should be deployed to masterchain (-1) + + // make sure we have a wallet mnemonic to deploy from (or create one if not found) + const deployConfigEnv = ".env"; + let deployerMnemonic; + if (!fs.existsSync(deployConfigEnv) || !process.env.DEPLOYER_MNEMONIC) { + console.log(`\n* Config file '${deployConfigEnv}' not found, creating a new wallet for deploy..`); + deployerMnemonic = (await mnemonicNew(24)).join(" "); + const deployWalletEnvContent = `DEPLOYER_WALLET=${deployerWalletType}\nDEPLOYER_MNEMONIC="${deployerMnemonic}"\n`; + fs.writeFileSync(deployConfigEnv, deployWalletEnvContent); + console.log(` - Created new wallet in '${deployConfigEnv}' - keep this file secret!`); + } else { + console.log(`\n* Config file '${deployConfigEnv}' found and will be used for deployment!`); + deployerMnemonic = process.env.DEPLOYER_MNEMONIC; } - if (await client.isContractDeployed(newContractAddress)) { - console.log(` - SUCCESS! Contract deployed successfully to address: ${newContractAddress.toFriendly()}`); - const contractBalance = await client.getBalance(newContractAddress); - console.log(` - New contract balance is now ${fromNano(contractBalance)} TON, make sure it has enough to pay rent`); - await performPostDeploymentTest(rootContract, deployInitScript, walletContract, walletKey.secretKey, newContractAddress); + + // open the wallet and make sure it has enough TON + const walletKey = await mnemonicToWalletKey(deployerMnemonic.split(" ")); + const walletContract = WalletContract.create(client, WalletV3R2Source.create({ + publicKey: walletKey.publicKey, + workchain + })); + console.log(` - Wallet address used to deploy from is: ${walletContract.address.toFriendly()}`); + const walletBalance = await client.getBalance(walletContract.address); + if (walletBalance.lt(toNano(0.2))) { + console.log(` - ERROR: Wallet has less than 0.2 TON for gas (${fromNano(walletBalance)} TON), please send some TON for gas first`); + process.exit(1); } else { - console.log(` - FAILURE! Contract address still looks uninitialized: ${newContractAddress.toFriendly()}`); + console.log(` - Wallet balance is ${fromNano(walletBalance)} TON, which will be used for gas`); } - } - console.log(``); + // go over all the contracts we have deploy scripts for + const rootContracts = glob.sync(["build/*.deploy.ts"]); + for (const rootContract of rootContracts) { + // deploy a new root contract + console.log(`\n* Found root contract '${rootContract} - let's deploy it':`); + const contractName = path.parse(path.parse(rootContract).name).name; + + // prepare the init data cell + const deployInitScript = require(__dirname + "/../" + rootContract); + if (typeof deployInitScript.initData !== "function") { + console.log(` - ERROR: '${rootContract}' does not have 'initData()' function`); + process.exit(1); + } + console.log(1); + const initDataCell = deployInitScript.initData() as Cell; + console.log(2); + + // prepare the init message + if (typeof deployInitScript.initMessage !== "function") { + console.log(` - ERROR: '${rootContract}' does not have 'initMessage()' function`); + process.exit(1); + } + console.log(1); + const initMessageCell = deployInitScript.initMessage() as Cell | null; + + // prepare the init code cell + const hexArtifact = `build/${contractName}.compiled.json`; + if (!fs.existsSync(hexArtifact)) { + console.log(` - ERROR: '${hexArtifact}' not found, did you build?`); + process.exit(1); + } + const initCodeCell = Cell.fromBoc(JSON.parse(fs.readFileSync(hexArtifact).toString()).hex)[0]; + + // make sure the contract was not already deployed + const newContractAddress = contractAddress({workchain, initialData: initDataCell, initialCode: initCodeCell}); + console.log(` - Based on your init code+data, your new contract address is: ${newContractAddress.toFriendly()}`); + if (await client.isContractDeployed(newContractAddress)) { + console.log(` - Looks like the contract is already deployed in this address, skipping deployment`); + await performPostDeploymentTest(rootContract, deployInitScript, walletContract, walletKey.secretKey, newContractAddress); + continue; + } + + // deploy by sending an internal message to the deploying wallet + console.log(` - Let's deploy the contract on-chain..`); + const seqno = await walletContract.getSeqNo(); + const transfer = walletContract.createTransfer({ + secretKey: walletKey.secretKey, + seqno: seqno, + sendMode: SendMode.PAY_GAS_SEPARATLY + SendMode.IGNORE_ERRORS, + order: new InternalMessage({ + to: newContractAddress, + value: newContractFunding, + bounce: false, + body: new CommonMessageInfo({ + stateInit: new StateInit({data: initDataCell, code: initCodeCell}), + body: initMessageCell !== null ? new CellMessage(initMessageCell) : null, + }), + }), + }); + await client.sendExternalMessage(walletContract, transfer); + console.log(` - Deploy transaction sent successfully`); + + // make sure that the contract was deployed + console.log(` - Block explorer link: https://${process.env.TESTNET ? "test." : ""}tonwhales.com/explorer/address/${newContractAddress.toFriendly()}`); + console.log(` - Waiting up to 20 seconds to check if the contract was actually deployed..`); + for (let attempt = 0; attempt < 10; attempt++) { + await sleep(2000); + const seqnoAfter = await walletContract.getSeqNo(); + if (seqnoAfter > seqno) break; + } + if (await client.isContractDeployed(newContractAddress)) { + console.log(` - SUCCESS! Contract deployed successfully to address: ${newContractAddress.toFriendly()}`); + const contractBalance = await client.getBalance(newContractAddress); + console.log(` - New contract balance is now ${fromNano(contractBalance)} TON, make sure it has enough to pay rent`); + await performPostDeploymentTest(rootContract, deployInitScript, walletContract, walletKey.secretKey, newContractAddress); + } else { + console.log(` - FAILURE! Contract address still looks uninitialized: ${newContractAddress.toFriendly()}`); + } + } + + console.log(``); } main(); @@ -151,14 +159,14 @@ main(); // helpers function sleep(ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); + return new Promise((resolve) => setTimeout(resolve, ms)); } async function performPostDeploymentTest(rootContract: string, deployInitScript: any, walletContract: WalletContract, secretKey: Buffer, newContractAddress: Address) { - if (typeof deployInitScript.postDeployTest !== "function") { - console.log(` - Not running a post deployment test, '${rootContract}' does not have 'postDeployTest()' function`); - return; - } - console.log(` - Running a post deployment test:`); - await deployInitScript.postDeployTest(walletContract, secretKey, newContractAddress); + if (typeof deployInitScript.postDeployTest !== "function") { + console.log(` - Not running a post deployment test, '${rootContract}' does not have 'postDeployTest()' function`); + return; + } + console.log(` - Running a post deployment test:`); + await deployInitScript.postDeployTest(walletContract, secretKey, newContractAddress); } diff --git a/build/nft-collection.deploy.ts b/build/nft-collection.deploy.ts index acdb260..e3f0973 100644 --- a/build/nft-collection.deploy.ts +++ b/build/nft-collection.deploy.ts @@ -1,15 +1,16 @@ import * as main from "../contracts/main"; import { Address, toNano, TupleSlice, WalletContract } from "ton"; // import { sendInternalMessageWithWallet } from "../test/helpers"; -import { hex } from "../build/nft-item.compiled.json"; +import {hex as item_code} from "../build/nft-item.compiled.json"; import { Builder, Cell, Slice } from "ton"; +import BN from "bn.js"; // return the init Cell of the contract storage (according to load_data() contract method) export function initData() { return main.collectionData({ ownerAddress: Address.parseFriendly("kQBw4_jZTQVbOSDbUjAMibTHWbstrCqjOnzvUTCphGpTFDrK").address, - code: Cell.fromBoc(hex)[0], - ownerKey: 0 // 63181357919630091755807889549433422416741950993093777020964723182484811889834 + code: Cell.fromBoc(item_code)[0], + ownerKey: new BN(0) // 63181357919630091755807889549433422416741950993093777020964723182484811889834 }); } diff --git a/contracts/imports/dns-utils.fc b/contracts/imports/dns-utils.fc index efc0227..cffc9b0 100644 --- a/contracts/imports/dns-utils.fc +++ b/contracts/imports/dns-utils.fc @@ -200,7 +200,7 @@ int price_function(int length, int multiplierx10, int steepness) { if (length >= 9) { price = 10; } - price = (steepness * price + (10 - steepness) * 50) / 10; + price = (steepness * price + (10 - steepness) * 50) / 50; return price * one_ton * multiplierx10 / 10; } diff --git a/contracts/main.ts b/contracts/main.ts index af265aa..aba25b8 100644 --- a/contracts/main.ts +++ b/contracts/main.ts @@ -4,6 +4,7 @@ import {SmartContract} from "ton-contract-executor"; import {encodeOffChainContent, makeSnakeCell} from "./utils"; import {randomBytes} from "crypto"; import {keyPairFromSeed, KeyPair, sign, keyPairFromSecretKey} from "ton-crypto"; +import { hex as item_code } from "../build/nft-item.compiled.json"; import {randomAddress} from "../test/helpers"; import {hashCell} from "ton/dist/boc/boc"; @@ -29,7 +30,7 @@ export function data(params: { ownerAddress: Address; collectionAddress: Address .storeUint(0, 256) .storeAddress(params.collectionAddress) .storeAddress(params.ownerAddress) - .storeRef(encodeOffChainContent("https://agorata.io/collection.json")) // https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md + .storeRef(encodeOffChainContent(`https://api.agorata.io/collection/${params.domain}.json`)) // https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md .storeRef(makeSnakeCell(Buffer.from(params.domain))) .storeDict(null) .storeUint(0, 64).endCell(); @@ -39,16 +40,19 @@ export function data(params: { ownerAddress: Address; collectionAddress: Address export function collectionData(params: { code: Cell, ownerAddress: Address, ownerKey: BN, - price_multiplier?: number, price_steepness?: number + price_multiplier?: number, price_steepness?: number, zone?: string }): Cell { if (params.price_multiplier == undefined) { - params.price_multiplier = 10; + params.price_multiplier = 1; } if (params.price_steepness == undefined) { - params.price_steepness = 5; + params.price_steepness = 1; + } + if (params.zone == undefined) { + params.zone = "example"; } return beginCell() - .storeRef(encodeOffChainContent("https://agorata.io/collection.json")) + .storeRef(encodeOffChainContent(`https://api.agorata.io/data/${params.zone}.json`)) // https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md .storeRef(params.code) .storeRef(beginCell().storeUint(params.price_multiplier, 8).storeUint(params.price_steepness, 4).endCell()) .storeUint(params.ownerKey, 256) @@ -99,6 +103,17 @@ export function signBuy(domain: string, collectionAddress: Address, buyerAddress return asciiEncode(signature); } +export function getItemAddr(collectionAddress: Address, domain: string, workchain: number): Address { + let item_data_init = beginCell() + .storeUint(new BN(hashCell(beginCell().storeBuffer(Buffer.from(domain)).endCell())), 256) + .storeAddress(collectionAddress).endCell(); + let item_state_init = beginCell().storeUint(0, 2) + .storeDict(Cell.fromBoc(item_code)[0]) + .storeDict(item_data_init) + .storeUint(0, 1).endCell(); + return new Address(workchain, hashCell(item_state_init)); +} + export function TON(): number { return 1000000000; } @@ -119,6 +134,13 @@ export function createItem(params: { domain: String, signature?: String }): Cell .endCell(); } +export function setContent(params: { domain: string, zone: string }) { + return beginCell() + .storeUint(0x1a0b9d51 , 32) + .storeRef(encodeOffChainContent(`https://api.agorata.io/data/${params.zone}/${params.domain}.json`)) + .endCell(); +} + 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/package-lock.json b/package-lock.json index 1112cce..dfd0582 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { + "@tonconnect/protocol": "^2.0.1", "semver": "^7.3.7", "subcommand": "^2.1.1", "ton-compiler": "^2.0.0" @@ -303,6 +304,14 @@ "node": ">=10" } }, + "node_modules/@tonconnect/protocol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tonconnect/protocol/-/protocol-2.0.1.tgz", + "integrity": "sha512-jkSj6EKjIlHnJxrtxdlO7KqVJe41yrIgqamGZiqziKH6iwx0m9YyKvuIREd6CmWY2jbsev3BvBWqPp9KH6HrRw==", + "dependencies": { + "tweetnacl-util": "^0.15.1" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -1962,6 +1971,11 @@ "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", "dev": true }, + "node_modules/tweetnacl-util": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", + "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -2263,6 +2277,14 @@ "dev": true, "optional": true }, + "@tonconnect/protocol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tonconnect/protocol/-/protocol-2.0.1.tgz", + "integrity": "sha512-jkSj6EKjIlHnJxrtxdlO7KqVJe41yrIgqamGZiqziKH6iwx0m9YyKvuIREd6CmWY2jbsev3BvBWqPp9KH6HrRw==", + "requires": { + "tweetnacl-util": "^0.15.1" + } + }, "@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -3497,6 +3519,11 @@ "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", "dev": true }, + "tweetnacl-util": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", + "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", diff --git a/package.json b/package.json index 2127f90..d0fd478 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "node": ">=16.15.0" }, "dependencies": { + "@tonconnect/protocol": "^2.0.1", "semver": "^7.3.7", "subcommand": "^2.1.1", "ton-compiler": "^2.0.0" diff --git a/test/creation.spec.ts b/test/creation.spec.ts index f38dee2..ead285f 100644 --- a/test/creation.spec.ts +++ b/test/creation.spec.ts @@ -9,6 +9,7 @@ import * as main from "../contracts/main"; import { internalMessage, randomAddress } from "./helpers"; import { hex } from "../build/nft-collection.compiled.json"; +import {hex as item_code} from "../build/nft-item.compiled.json"; import {makeSnakeCell} from "../contracts/utils"; describe("Creating items tests", () => { @@ -20,7 +21,7 @@ describe("Creating items tests", () => { Cell.fromBoc(hex)[0], main.collectionData({ ownerAddress: randomAddress("owner"), - code: Cell.fromBoc(hex)[0], + code: Cell.fromBoc(item_code)[0], ownerKey: 0, }), { debug: debug } diff --git a/test/signing.spec.ts b/test/signing.spec.ts index d521613..24d2f40 100644 --- a/test/signing.spec.ts +++ b/test/signing.spec.ts @@ -10,6 +10,7 @@ import * as main from "../contracts/main"; import {internalMessage, randomAddress} from "./helpers"; import {hex} from "../build/nft-collection.compiled.json"; +import {hex as item_code} from "../build/nft-item.compiled.json"; import {makeSnakeCell} from "../contracts/utils"; import {keyPairFromSeed, KeyPair, sign, keyPairFromSecretKey} from "ton-crypto"; import {signBuy} from "../contracts/main"; @@ -18,7 +19,7 @@ let ownerKeys = keyPairFromSeed(Buffer.from("00000000000000000000000000000000000 let ownerPubNum = new BN(ownerKeys.publicKey); let data = main.collectionData({ ownerAddress: randomAddress("owner"), - code: Cell.fromBoc(hex)[0], + code: Cell.fromBoc(item_code)[0], ownerKey: ownerPubNum, });