Browse Source

We can now deploy items and have a cli

master
Lev 2 years ago
parent
commit
a028b5c7d3
  1. 63
      bin/cli.js
  2. 8
      build/_build.ts
  3. 266
      build/_deploy.ts
  4. 7
      build/nft-collection.deploy.ts
  5. 2
      contracts/imports/dns-utils.fc
  6. 32
      contracts/main.ts
  7. 27
      package-lock.json
  8. 1
      package.json
  9. 3
      test/creation.spec.ts
  10. 3
      test/signing.spec.ts

63
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());
}
}
]

8
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";

266
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);
}

7
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
});
}

2
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;
}

32
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();

27
package-lock.json generated

@ -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",

1
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"

3
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 }

3
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,
});

Loading…
Cancel
Save