Browse Source

Working on item's content

master
Lev 2 years ago
parent
commit
dbad552830
  1. 14
      bin/api.js
  2. 89
      contracts/main.ts
  3. 15
      contracts/utils.ts
  4. 23
      test/item.spec.ts

14
bin/api.js

@ -4,7 +4,7 @@ const {Base64} = require('@tonconnect/protocol');
const BN = require("bn.js"); const BN = require("bn.js");
const express = require('express') const express = require('express')
const {get_tonclient} = require("../contracts/utils"); const {get_tonclient, AdnlAddress} = require("../contracts/utils");
const {sha256} = require("ton-crypto"); const {sha256} = require("ton-crypto");
const {getRecords} = require("../contracts/main"); const {getRecords} = require("../contracts/main");
const app = express() const app = express()
@ -56,6 +56,18 @@ app.get('/get-records/:address', async (req, res) => {
} }
}) })
app.get('/set-record/site/:site', async (req, res) => {
let site = new AdnlAddress(req.params.site);
let msg = main.changeRecordMsg("site", await main.AdnlRecord(site));
res.send(JSON.stringify(Base64.encode(msg.toBoc())));
})
app.get('/set-record/wallet/:wallet', async (req, res) => {
let wallet = Address.parse(req.params.wallet);
let msg = main.changeRecordMsg("wallet", await main.WalletRecord(wallet));
res.send(JSON.stringify(Base64.encode(msg.toBoc())));
})
app.listen(port, () => { app.listen(port, () => {
console.log(`Example app listening on port ${port}`) console.log(`Example app listening on port ${port}`)
}) })

89
contracts/main.ts

@ -1,7 +1,14 @@
import BN from "bn.js"; import BN from "bn.js";
import {Cell, beginCell, Address, Slice, TonClient} from "ton"; import {Cell, beginCell, Address, Slice, TonClient} from "ton";
import {SmartContract} from "ton-contract-executor"; import {SmartContract} from "ton-contract-executor";
import {AdnlAddress, encodeOffChainContent, encodeSemiChainContent, makeSnakeCell} from "./utils"; import {
AdnlAddress,
categoryToBN,
decodeOffChainContent,
encodeOffChainContent,
encodeSemiChainContent,
makeSnakeCell
} from "./utils";
import {randomBytes} from "crypto"; import {randomBytes} from "crypto";
import {keyPairFromSeed, KeyPair, sign, keyPairFromSecretKey, sha256} from "ton-crypto"; import {keyPairFromSeed, KeyPair, sign, keyPairFromSecretKey, sha256} from "ton-crypto";
import { hex as item_code } from "../build/nft-item.compiled.json"; import { hex as item_code } from "../build/nft-item.compiled.json";
@ -84,24 +91,38 @@ export function itemData(params: {
} }
export async function getRecords(tonclient: TonClient, address: Address) { export async function getRecords(tonclient: TonClient, address: Address) {
let ans_wallet = (await tonclient.callGetMethod(address, 'dnsresolve',
[["tvm.Slice", "te6cckEBAQEAAwAAAgDTZ9xB"],
["num", new BN(await sha256('wallet')).toString()]])).stack[1];
let wallet = null; let wallet = null;
if (ans_wallet[1].bytes !== undefined) { try {
wallet = Cell.fromBoc(Buffer.from(ans_wallet[1].bytes, 'base64'))[0]; let ans_wallet = (await tonclient.callGetMethod(address, 'dnsresolve',
} [["tvm.Slice", "te6cckEBAQEAAwAAAgDTZ9xB"],
let ans_site = (await tonclient.callGetMethod(address, 'dnsresolve', ["num", new BN(await sha256('wallet')).toString()]])).stack[1];
[["tvm.Slice", "te6cckEBAQEAAwAAAgDTZ9xB"], if (ans_wallet[1].bytes !== undefined) {
["num", new BN(await sha256('site')).toString()]])).stack[1]; wallet = Cell.fromBoc(Buffer.from(ans_wallet[1].bytes, 'base64'))[0].beginParse().readAddress();
}
} catch (e) {}
let site = null; let site = null;
if (ans_site[1].bytes !== undefined) { try {
let site_data = ans_site[1].bytes; // object.data.b64; let ans_site = (await tonclient.callGetMethod(address, 'dnsresolve',
// print site_data converted from base64 [["tvm.Slice", "te6cckEBAQEAAwAAAgDTZ9xB"],
let c = Cell.fromBoc(Buffer.from(site_data, 'base64'))[0]; ["num", new BN(await sha256('site')).toString()]])).stack[1];
site = new AdnlAddress(c.bits.buffer.subarray(2, 2 + 32)).toHex(); if (ans_site[1].bytes !== undefined) {
let site_data = ans_site[1].bytes; // object.data.b64;
// print site_data converted from base64
let c = Cell.fromBoc(Buffer.from(site_data, 'base64'))[0];
site = new AdnlAddress(c.bits.buffer.subarray(2, 2 + 32)).toHex();
}
} catch (e) {}
let uri = null;
try {
let ans_uri = (await tonclient.callGetMethod(address, 'dnsresolve',
[["tvm.Slice", "te6cckEBAQEAAwAAAgDTZ9xB"],
["num", new BN(await sha256('uri')).toString()]])).stack[1];
uri = Buffer.from(ans_uri[1].bytes, 'base64').toString();
} catch (e) {
console.log(e);
console.log((await tonclient.callGetMethod(address, 'get_nft_data')).stack[4]);
} }
return {wallet, site}; return {wallet, site, uri};
} }
@ -159,6 +180,31 @@ export function TON(): number {
return 1000000000; return 1000000000;
} }
export async function changeRecordMsg(category: string, value: Cell | null) {
let cell = beginCell()
.storeUint(0x4eb1f0f9, 32)
.storeUint(0, 64)
.storeUint(new BN(await categoryToBN(category)), 256);
if (value) {
cell.storeRef(value);
}
return cell.endCell();
}
export async function AdnlRecord(site: AdnlAddress) {
return beginCell()
.storeUint(0xad01, 16)
.storeBuffer(<Buffer>site.bytes)
.storeUint(0, 8).endCell();
}
export async function WalletRecord(wallet: Address) {
return beginCell()
.storeUint(0x9fd3, 16)
.storeAddress(wallet)
.storeUint(0, 8).endCell();
}
// message encoders for all ops (see contracts/imports/constants.fc for consts) // message encoders for all ops (see contracts/imports/constants.fc for consts)
export function transferOwnership(params: { newOwnerAddress: Address }): Cell { export function transferOwnership(params: { newOwnerAddress: Address }): Cell {
@ -187,11 +233,12 @@ async function itemContent(domain: string, zone: string): Promise<Cell> {
} }
export async function setContent(params: { domain: string, zone: string }) { export async function setContent(params: { domain: string, zone: string }) {
return beginCell() // return beginCell()
.storeUint(0x1a0b9d51, 32) // .storeUint(0x1a0b9d51, 32)
.storeUint(0, 64) // .storeUint(0, 64)
.storeRef(await itemContent(params.domain, params.zone)) // .storeRef(await itemContent(params.domain, params.zone))
.endCell(); // .endCell();
return changeRecordMsg("uri", beginCell().storeBuffer(Buffer.from(`https://api.agorata.io/data/${params.zone}/${params.domain}.json`)).endCell());
} }
export function loadRecords(map_cell: Cell) { export function loadRecords(map_cell: Cell) {

15
contracts/utils.ts

@ -1,5 +1,6 @@
import {beginCell, beginDict, BitString, Cell, DictBuilder, TonClient} from "ton"; import {beginCell, beginDict, BitString, Cell, DictBuilder, TonClient} from "ton";
import {sha256} from "ton-crypto"; import {sha256} from "ton-crypto";
import {BN} from "bn.js";
// from https://github.com/getgems-io/nft-contracts/blob/main/packages/nft-content/nftContent.ts // from https://github.com/getgems-io/nft-contracts/blob/main/packages/nft-content/nftContent.ts
@ -69,10 +70,10 @@ export async function encodeSemiChainContent(uri: string) {
export function decodeOffChainContent(content: Cell) { export function decodeOffChainContent(content: Cell) {
let data = flattenSnakeCell(content) let data = flattenSnakeCell(content)
let prefix = data[0] // let prefix = data[0]
if (prefix !== OFF_CHAIN_CONTENT_PREFIX) { // if (prefix !== OFF_CHAIN_CONTENT_PREFIX) {
throw new Error(`Unknown content prefix: ${prefix.toString(16)}`) // throw new Error(`Unknown content prefix: ${prefix.toString(16)}`)
} // }
return data.slice(1).toString() return data.slice(1).toString()
} }
@ -165,3 +166,9 @@ export class AdnlAddress {
return hex; return hex;
} }
} }
export async function categoryToBN(category: string) {
if (!category) return new BN(0); // all categories
const categoryHash = await sha256(category);
return new BN(categoryHash);
}

23
test/item.spec.ts

@ -4,15 +4,16 @@ import BN from "bn.js";
chai.use(chaiBN(BN)); chai.use(chaiBN(BN));
import {Address, Builder, Cell, contractAddress, Slice} from "ton"; import {Address, beginCell, Builder, Cell, contractAddress, parseDict, parseDictBitString, Slice} from "ton";
import {runContract, SmartContract} from "ton-contract-executor"; import {runContract, SmartContract} from "ton-contract-executor";
import * as main from "../contracts/main"; import * as main from "../contracts/main";
import {internalMessage, randomAddress} from "./helpers"; import {internalMessage, randomAddress} from "./helpers";
import {hex as item_code} from "../build/nft-item.compiled.json"; import {hex as item_code} from "../build/nft-item.compiled.json";
import {makeSnakeCell} from "../contracts/utils"; import {makeSnakeCell} from "../contracts/utils";
import {keyPairFromSeed, KeyPair, sign, keyPairFromSecretKey} from "ton-crypto"; import {keyPairFromSeed, KeyPair, sign, keyPairFromSecretKey, sha256} from "ton-crypto";
import {signBuy} from "../contracts/main"; import {signBuy} from "../contracts/main";
import {Base64} from "@tonconnect/protocol";
let data = main.itemDataUninit({domain: "test", collectionAddress: randomAddress("collection")}); let data = main.itemDataUninit({domain: "test", collectionAddress: randomAddress("collection")});
@ -35,7 +36,7 @@ describe("Creating items tests", () => {
let ownerAddr = randomAddress("dude"); let ownerAddr = randomAddress("dude");
const initializeMsg = internalMessage({ const initializeMsg = internalMessage({
from: randomAddress("collection"), from: randomAddress("collection"),
body: main.initializeItemMsg({domain: "test", ownerAddr}), body: main.initializeItemMsg({domain: "levcccc", ownerAddr}),
value: new BN(0), value: new BN(0),
}); });
const res = await contract.sendInternalMessage(initializeMsg); const res = await contract.sendInternalMessage(initializeMsg);
@ -46,16 +47,24 @@ describe("Creating items tests", () => {
expect(res.exit_code).to.equal(0); expect(res.exit_code).to.equal(0);
const setDataMsg = internalMessage({ const setDataMsg = internalMessage({
from: ownerAddr, from: ownerAddr,
body: await main.setContent({domain: "test", zone: "example.ton"}), body: await main.setContent({domain: "levcccc", zone: "example.ton"}),
value: new BN(0), value: new BN(0),
}) })
const res2 = await contract.sendInternalMessage(setDataMsg); const res2 = await contract.sendInternalMessage(setDataMsg);
expect(res2.type).to.equal("success"); expect(res2.type).to.equal("success");
expect(res2.exit_code).to.equal(0); expect(res2.exit_code).to.equal(0);
let nft_data = await contract.invokeGetMethod("get_nft_data", []); let nft_data = await contract.invokeGetMethod("get_nft_data", []);
console.log(nft_data.result); console.log('res4', nft_data.result[4]);
// @ts-ignore // @ts-ignore
let content = (nft_data.result[4] as Slice); console.log(Base64.encode((nft_data.result[4] as Cell).toBoc()))
// @ts-ignore
// let content = (nft_data.result[4] as Cell).beginParse();
// let a = parseDict(content, 256, (s) => s);
// console.log(a);
let resolved = (await contract.invokeGetMethod("dnsresolve", [
{type: "cell_slice", value: "te6cckEBAQEAAwAAAgDTZ9xB"},
{type: "int", value: new BN(await sha256('uri')).toString()}
]));
expect(resolved.type).to.equal("success");
}); });
}); });

Loading…
Cancel
Save