Browse Source

Working on item's content

master
Lev 2 years ago
parent
commit
dbad552830
  1. 14
      bin/api.js
  2. 67
      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 express = require('express')
const {get_tonclient} = require("../contracts/utils");
const {get_tonclient, AdnlAddress} = require("../contracts/utils");
const {sha256} = require("ton-crypto");
const {getRecords} = require("../contracts/main");
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, () => {
console.log(`Example app listening on port ${port}`)
})

67
contracts/main.ts

@ -1,7 +1,14 @@
import BN from "bn.js";
import {Cell, beginCell, Address, Slice, TonClient} from "ton";
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 {keyPairFromSeed, KeyPair, sign, keyPairFromSecretKey, sha256} from "ton-crypto";
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) {
let wallet = null;
try {
let ans_wallet = (await tonclient.callGetMethod(address, 'dnsresolve',
[["tvm.Slice", "te6cckEBAQEAAwAAAgDTZ9xB"],
["num", new BN(await sha256('wallet')).toString()]])).stack[1];
let wallet = null;
if (ans_wallet[1].bytes !== undefined) {
wallet = Cell.fromBoc(Buffer.from(ans_wallet[1].bytes, 'base64'))[0];
wallet = Cell.fromBoc(Buffer.from(ans_wallet[1].bytes, 'base64'))[0].beginParse().readAddress();
}
} catch (e) {}
let site = null;
try {
let ans_site = (await tonclient.callGetMethod(address, 'dnsresolve',
[["tvm.Slice", "te6cckEBAQEAAwAAAgDTZ9xB"],
["num", new BN(await sha256('site')).toString()]])).stack[1];
let site = null;
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();
}
return {wallet, site};
} 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, uri};
}
@ -159,6 +180,31 @@ export function TON(): number {
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)
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 }) {
return beginCell()
.storeUint(0x1a0b9d51, 32)
.storeUint(0, 64)
.storeRef(await itemContent(params.domain, params.zone))
.endCell();
// return beginCell()
// .storeUint(0x1a0b9d51, 32)
// .storeUint(0, 64)
// .storeRef(await itemContent(params.domain, params.zone))
// .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) {

15
contracts/utils.ts

@ -1,5 +1,6 @@
import {beginCell, beginDict, BitString, Cell, DictBuilder, TonClient} from "ton";
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
@ -69,10 +70,10 @@ export async function encodeSemiChainContent(uri: string) {
export function decodeOffChainContent(content: Cell) {
let data = flattenSnakeCell(content)
let prefix = data[0]
if (prefix !== OFF_CHAIN_CONTENT_PREFIX) {
throw new Error(`Unknown content prefix: ${prefix.toString(16)}`)
}
// let prefix = data[0]
// if (prefix !== OFF_CHAIN_CONTENT_PREFIX) {
// throw new Error(`Unknown content prefix: ${prefix.toString(16)}`)
// }
return data.slice(1).toString()
}
@ -165,3 +166,9 @@ export class AdnlAddress {
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));
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 * as main from "../contracts/main";
import {internalMessage, randomAddress} from "./helpers";
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 {keyPairFromSeed, KeyPair, sign, keyPairFromSecretKey, sha256} from "ton-crypto";
import {signBuy} from "../contracts/main";
import {Base64} from "@tonconnect/protocol";
let data = main.itemDataUninit({domain: "test", collectionAddress: randomAddress("collection")});
@ -35,7 +36,7 @@ describe("Creating items tests", () => {
let ownerAddr = randomAddress("dude");
const initializeMsg = internalMessage({
from: randomAddress("collection"),
body: main.initializeItemMsg({domain: "test", ownerAddr}),
body: main.initializeItemMsg({domain: "levcccc", ownerAddr}),
value: new BN(0),
});
const res = await contract.sendInternalMessage(initializeMsg);
@ -46,16 +47,24 @@ describe("Creating items tests", () => {
expect(res.exit_code).to.equal(0);
const setDataMsg = internalMessage({
from: ownerAddr,
body: await main.setContent({domain: "test", zone: "example.ton"}),
body: await main.setContent({domain: "levcccc", zone: "example.ton"}),
value: new BN(0),
})
const res2 = await contract.sendInternalMessage(setDataMsg);
expect(res2.type).to.equal("success");
expect(res2.exit_code).to.equal(0);
let nft_data = await contract.invokeGetMethod("get_nft_data", []);
console.log(nft_data.result);
console.log('res4', nft_data.result[4]);
// @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