Skip to content

Commit

Permalink
dns update
Browse files Browse the repository at this point in the history
  • Loading branch information
tolya-yanot committed Jun 24, 2022
1 parent 97103ae commit 5a0bc67
Show file tree
Hide file tree
Showing 9 changed files with 402 additions and 151 deletions.
2 changes: 1 addition & 1 deletion dist/tonweb.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tonweb",
"version": "0.0.44",
"version": "0.0.45",
"description": "TonWeb - JavaScript API for TON blockchain",
"main": "src/index.js",
"types": "dist/types/index.d.ts",
Expand Down
124 changes: 26 additions & 98 deletions src/contract/dns/Dns.js
Original file line number Diff line number Diff line change
@@ -1,99 +1,21 @@
const {parseAddress} = require("../token/nft/NftUtils");
const {Cell} = require("../../boc");
const {bytesToBase64} = require("../../utils");
const Address = require("../../utils/Address").default;
const {BN, Address} = require("../../utils");
const {
DNS_CATEGORY_NEXT_RESOLVER,
DNS_CATEGORY_SITE,
DNS_CATEGORY_WALLET,
createSmartContractAddressRecord,
createAdnlAddressRecord,
createNextResolverRecord,
parseNextResolverRecord,
parseSmartContractAddressRecord,
dnsResolve
} = require("./DnsUtils");

// ATTENTION: This is BETA, will be changed

const DNS_CATEGORY_ALL = 0;
const DNS_CATEGORY_ADNL_ADDRESS = 1;
const DNS_CATEGORY_WALLET_ADDRESS = 2;

// Need to get this address from network Config #4
const rootDnsAddress = '-1:EAC391A15AD065447024AE74D55EB5E61F8B7FCE48F68EEF5981B07ECC4C094A';

/**
* @param cell {Cell}
* @return {Address|null}
*/
const parseAddressFromDns = (cell) => {
// cell.bits.array = cell.bits.array.slice(2); // skip first 16 bits
return parseAddress(cell);
}

/**
* @private
* @param provider {HttpProvider}
* @param dnsAddress {string}
* @param rawDomainBytes {Uint8Array}
* @param category {number}
* @param noRecursive {boolean}
* @returns {Promise<Cell|Address|null>}
*/
const dnsResolveImpl = async (provider, dnsAddress, rawDomainBytes, category, noRecursive) => {
const len = rawDomainBytes.length * 8;
// console.log('>', len)

const domainCell = new Cell()
domainCell.bits.writeBytes(rawDomainBytes)

const result = await provider.call2(dnsAddress, 'dnsresolve', [['tvm.Slice', bytesToBase64(await domainCell.toBoc(false))], ['num', category]]);
const resultLen = result[0].toNumber();
const cell = result[1];
// console.log('<', resultLen, cell);
if (resultLen > len) {
throw new Error('invalid response ' + resultLen + '/' + len);
} else if (resultLen === len) {
if (category === DNS_CATEGORY_WALLET_ADDRESS) {
return parseAddressFromDns(cell);
} else {
return cell;
}
} else {
if (cell === null) {
return null; // domain cannot be resolved
} else {
const nextAddress = parseAddressFromDns(cell);
// console.log('NEXT=', nextAddress.toString(true, true, true));
if (noRecursive) {
return nextAddress;
} else {
return await dnsResolveImpl(provider, nextAddress.toString(), rawDomainBytes.slice(0, resultLen / 8), category);
}
}
}
}

/**
* @param provider {HttpProvider}
* @param rootDnsAddress {string}
* @param domain {string} e.g "sub.alice.ton"
* @param category {number}
* @param noRecursive {boolean}
* @returns {Promise<Cell|Address|null>}
*/
const dnsResolve = async (provider, rootDnsAddress, domain, category, noRecursive) => {
domain = domain.toLowerCase();

for (let i = 0; i < domain.length; i++) {
if (domain.charAt(i) <= 32) {
throw new Error('Bytes in range 0..32 are not allowed in domain names');
}
}

const arr = domain.split('.');

arr.forEach(part => {
if (!part.length) {
throw new Error('Invalid domain');
}
});

const rawDomain = arr.reverse().join('\0') + '\0';
const rawDomainBytes = new TextEncoder().encode(rawDomain);
// console.log('>', domain, rawDomainBytes)
return dnsResolveImpl(provider, rootDnsAddress, rawDomainBytes, category, noRecursive);
}
const rootDnsAddress = 'Ef9xOk_ikGYvhgL0ruRGOrPTiOgm_2XlLiUBgQYMzjdSEgDP';

class Dns {
/**
Expand All @@ -112,17 +34,23 @@ class Dns {

/**
* @param domain {string} e.g "sub.alice.ton"
* @param category {number}
* @returns {Promise<Cell|Address|null>}
* @param category {string | undefined} category of requested DNS record, null for all categories
* @param oneStep {boolean | undefined} non-recursive
* @returns {Promise<Map<String, Cell | Address | BN> | Cell | null>}
*/
resolve(domain, category) {
return dnsResolve(this.provider, rootDnsAddress, domain, category)
resolve(domain, category, oneStep) {
return dnsResolve(this.provider, rootDnsAddress, domain, category, oneStep)
}
}

Dns.resolve = dnsResolve;
Dns.DNS_CATEGORY_ALL = DNS_CATEGORY_ALL;
Dns.DNS_CATEGORY_ADNL_ADDRESS = DNS_CATEGORY_ADNL_ADDRESS;
Dns.DNS_CATEGORY_WALLET_ADDRESS = DNS_CATEGORY_WALLET_ADDRESS;
Dns.createSmartContractAddressRecord = createSmartContractAddressRecord;
Dns.createAdnlAddressRecord = createAdnlAddressRecord;
Dns.createNextResolverRecord = createNextResolverRecord;
Dns.parseNextResolverRecord = parseNextResolverRecord;
Dns.parseSmartContractAddressRecord = parseSmartContractAddressRecord;
Dns.DNS_CATEGORY_NEXT_RESOLVER = DNS_CATEGORY_NEXT_RESOLVER;
Dns.DNS_CATEGORY_WALLET = DNS_CATEGORY_WALLET;
Dns.DNS_CATEGORY_SITE = DNS_CATEGORY_SITE;

module.exports.default = Dns;
23 changes: 13 additions & 10 deletions src/contract/dns/DnsCollection.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
const {Contract} = require("../../contract/index.js");
const {Cell} = require("../../boc");
const {Address, bytesToBase64} = require("../../utils");
const {Address} = require("../../utils");
const {parseAddress} = require('../token/nft/NftUtils.js');
const {default: DNS} = require("./DNS");
const {dnsResolve} = require("./DnsUtils.js")
const {parseOffchainUriCell} = require("../token/nft/NftUtils");

// ATTENTION: This is BETA, will be changed

Expand All @@ -13,15 +14,15 @@ class DnsCollection extends Contract {
*/
constructor(provider, options) {
options.wc = 0;
options.code = options.code || Cell.oneFromBoc('B5EE9C7241021401000172000114FF00F4A413F4BCF2C80B0102016202030202CC04050201200E0F02012006070039DACF8033810F803BBC00C646582AC678B387D0165B5E66664C0207D80402012008090201580C0D00C743221C70094840FF2F0DED0D3030171B0915BE0FA403001D31FED44D0D4D4303122C0008E323220D74920C218F2E0C8208103F8BBF2E0C978A908C000F2E0CA20F003F2E0CB20F901C858CF16C9C85004CF1613CCC9F008E010235F03C007DC840FF2F080201200A0B00311C278074C1C07000082CE4C0A900B784B98C4830003CB43260004F1C0875D26AC0A386D72E882CE3850C00B4C1C8704840B00B84AC482CE4C0A900B784F7B99B04AEA0002D007232FFFE0A33C5B25C083232C044FD003D0032C03260001B3E401D3232C084B281F2FFF27420020120101102012012130007B8B5D318001FBA7A3ED44D0D4D43031F0067001F00780019B905BED44D0D4D4303070016D80037BA30C3020F002AA02D71830F90170C802820167A3ED43D812CF16C9813EFF73B');
options.code = options.code || Cell.oneFromBoc('B5EE9C72410216010001D6000114FF00F4A413F4BCF2C80B0102016202030202CC0405020120101102012006070201D40E0F02012008090201200C0D00CB43221C70094840FF2F0DED0D3030171B0915BE0FA403001D31FED44D0D4D4303122C0008E3432F00320D74920C218F2E0C8208103F8BBF2E0C978A908C000F2E0CA20F004F2E0CB20F901C858CF16C9C85004CF1613CCC9F009E010235F03C007DC840FF2F080201200A0B00331C27C074C1C07000082CE500A98200B784B98C4830003CB43260004F3223880875D244B5C61673C58875D2883000082CE6C070007CB837C0B50C3400A44C78B98C727420004D47021D7498E1C5CBA20B38E153002D30721C12102C02E12B120B39402A60802DE13DEE66C12BA8002D501C8CBFFF828CF16C97020C8CB0113F400F400CB00C98001B3E401D3232C084B281F2FFF274200039167C01DC087C021DE0063232C15633C59C3E80B2DAF3333260103EC020020120121302012014150007B8B5D318001FBA7A3ED44D0D4D43031F0077001F00880019B905BED44D0D4D4303070016D8009DBA30C3020D74978A908C000F2E04D20D70A07C00021D749C0085210B0935B786DE0209501D3073101DE21F0025122D71830F9018200BA93C8CB0F01820167A3ED43D8CF16C90191789170E212A001814FBFC8D');
super(provider, options);

if (!options.collectionContent && !options.address) throw new Error('required collectionContent cell');

this.methods.getCollectionData = this.getCollectionData.bind(this);
this.methods.getNftItemAddressByIndex = this.getNftItemAddressByIndex.bind(this);
this.methods.getNftItemContent = this.getNftItemContent.bind(this);
this.methods.dnsResolve = this.dnsResolve.bind(this);
this.methods.resolve = this.resolve.bind(this);
}

/**
Expand All @@ -44,12 +45,13 @@ class DnsCollection extends Contract {
const result = await this.provider.call2(myAddress.toString(), 'get_collection_data');

const collectionContent = result[1];
const collectionContentUri = parseOffchainUriCell(collectionContent);

return {collectionContent};
return {collectionContentUri, collectionContent, ownerAddress: null, nextItemIndex: 0};
}

/**
* @param nftItem {NFTItem}
* @param nftItem {DnsItem}
* @return {Promise<{isInitialized: boolean, index: BN, collectionAddress: Address|null, ownerAddress: Address|null, contentCell: Cell}>}
*/
async getNftItemContent(nftItem) {
Expand All @@ -70,12 +72,13 @@ class DnsCollection extends Contract {

/**
* @param domain {string} e.g "sub.alice.ton"
* @param category {number}
* @returns {Promise<Address>}
* @param category? {string} category of requested DNS record, null for all categories
* @param oneStep? {boolean} non-recursive
* @returns {Promise<Map<String, Cell | Address | BN> | Cell | null>}
*/
async dnsResolve(domain, category) {
async resolve(domain, category, oneStep) {
const myAddress = await this.getAddress();
return DNS.resolve(this.provider, myAddress.toString(), domain, category, true)
return dnsResolve(this.provider, myAddress.toString(), domain, category, oneStep);
}
}

Expand Down
34 changes: 25 additions & 9 deletions src/contract/dns/DnsItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ const {Contract} = require("../../contract/index.js");
const {Cell} = require("../../boc");
const {Address, BN} = require("../../utils");
const {parseAddress} = require('./../token/nft/NftUtils.js');
const DNS = require('./DNS.js').default;

const DNS_ITEM_CODE_HEX = 'B5EE9C7241022201000471000114FF00F4A413F4BCF2C80B0102016202030202CC04050201201A1B0201200607002BD836465FFA802E78B2801E78B66667A00659FE4F6AA4020120080902012014150201200A0B00314709E01D30701C00020B39302A402DE12E63120C000F2D0C9803F7007434C0C05C6C2497C1383E903E900C7E800C5C75C87E800C7E800C3C01C9ECE38C57C15B088D5490B1C17CB8655B5C3232C1FD003240BE90350C3E08E082024EA0283C0110D9BC01840944090408FE08FC023814D671C1462C38C08A71C0245C254274C7D42AB8887C017E08C86F09300038C08FD6C2F4CFC8DBA00C0D0E00113E910C1C2EBCB8536000665F096C12FA403070206D211045708010C8CB055007CF165005FA0215CB6A12CB1FCB3F226EB39458CF17019132E201C901FB0000EE343A3A3B8E1636363737375135C705F2E07B102510241023F823F0088E58305396BCF2E07B820AFAF08052B0A15270BC9836820AFAF0801AA1933A0905E270206D21105B708010C8CB055007CF165005FA0215CB6A12CB1FCB3F226EB39458CF17019132E201C901FB004464F00610451024F823F008E203FAB31EB096323409036D01913BE2F82328A18209E14320BC226EB08E1A5B6C55F004F8238208093A80A04470F0061045103412F823F008E082105FCC3D145210BAE302383B82102FCB26A25270BAE3023882101A0B9D515260BA8E1430345143C705F2E19A05D430105610354433F008E0058104D2BAE3025F09840FF2F00F101102B630105A104910385E4255025168C705F2E19103FA4021F001FA40D20031FA00820AFAF0801EA121945315A0A1DE22D70B01C300209206A19136E220C2FFF2E1922194102D3A5BE30D02951029333530E30D1056104510344033F0081213007C5F0336365B7082108B77173505C8CBFF5004CF1644408040708010C8CB055007CF165005FA0215CB6A12CB1FCB3F226EB39458CF17019132E201C901FB0000585155C705F2E19A06D3FFD43004D0D30701C000F2E750F4043010248307F41770C8CB07F400C946134444F008007C821005138D91C8500CCF16500ECF1671244C145449D0708010C8CB055007CF165005FA0215CB6A12CB1FCB3F226EB39458CF17019132E201C901FB00107A006A29F0018210D53276DB103A47046D71708010C8CB055007CF165005FA0215CB6A12CB1FCB3F226EB39458CF17019132E201C901FB0002012016170201201819000D1C3232C07274200021081BA50C1B5C0838343E903E8034CFCC200017321400F3C5807E80B2CFF26000513B513434FFFE900835D2708027DFC07E9035353D0134CFCC0415C415B80C1C1B5B5B5B490415C415A00201201C1D0201201E1F0013BBB39F007175F07F0058000DBA559F0076C718000DB8FCFF0075F03802012020210013B64A5E00E204EBE0FA1000E7B461843AE9356054A45E00441540429AE3061E00EB6D885A041AE934C10A0678E0B6728BE0AE0DBC0A049791C4705E033E04883DCB11FB64DDC4964AD1BA06B879240DC23572F37CC5CAAAB143A2FFE65BC05A1A60E038001E5CEA1E808604380012263C1060FE81CDF432B90039E2D93C060DB063B05FEA';
const {dnsResolve, categoryToBN} = require("./DnsUtils.js")

// ATTENTION: This is BETA, will be changed

const DNS_ITEM_CODE_HEX = 'B5EE9C72410224010004E9000114FF00F4A413F4BCF2C80B0102016202030202CC04050201201B1C02012006070201D4191A0201480809020120151603F7007434C0C05C6C2497C1383E903E900C7E800C5C75C87E800C7E800C3C0209ECE38BD7C15B088D5490B1C17CB8655B5C3232C1FD003240BE90350C3E08E0404B283C0150D9BC01C40944090408FE08FC027814D671C1462C38C08A71C0245C254274C7D42AB8887C01BE08C86F09300038C08FD6C2F4CFC8DBACC7A00A0B0C00113E910C1C2EBCB853600066109B5F0BFA40307053006D8040708010C8CB055007CF165005FA0215CB6A12CB1FCB3F226EB39458CF17019132E201C901FB0001E0343A3A3B8E68305396BCF2E07B820AFAF08052B0A15270BC9836820AFAF0801AA1933A0905E270206D21105B708010C8CB055007CF165005FA0215CB6A12CB1FCB3F226EB39458CF17019132E201C901FB007A23F823A1A120C2009313A0029130E24464F00710451024F823F009E30D0D03FEB096323409036D01913BE2F82328A18209E14320BC226EB08E185B6C55F005F82381012CA04470F0071045103412F823F009E082105FCC3D145210BA8E92305383C705F2E191105A104910385E425502E082102FCB26A25210BAE30282101A0B9D515210BA8E183032353536375134C705F2E19A04D43040155044F823F009110E0F002C36363737375135C705F2E07B102510241023F823F009007C5F0536365B7082108B77173505C8CBFF5004CF1644408040708010C8CB055007CF165005FA0215CB6A12CB1FCB3F226EB39458CF17019132E201C901FB00017AE0208104D2BA8E26303738395155C705F2E19B06D3FF3120D74A31C20027D0D30730C000F2E7503006034444F009E03B0A813039BAE3025F0B840FF2F01001DC810309F833D0F4043052508307F40E6FA18ED7D30721C0008E932510BD107A09105810471046105D4313504D1C96303B5F036C61E201C0018E2D7053006D8100A0708010C8CB055007CF165005FA0215CB6A12CB1FCB3F226EB39458CF17019132E201C901FB009130E2925F0CE21103F63603FA4021F001FA40D20031FA00820AFAF0801EA121945315A0A1DE22D70B01C300209206A19136E220C2FFF2E192218E3E821005138D91C8500CCF16500ECF1671244C145449D0708010C8CB055007CF165005FA0215CB6A12CB1FCB3F226EB39458CF17019132E201C901FB00107A94102D3A5BE202E30F1056121314006A29F0018210D53276DB103A47046D71708010C8CB055007CF165005FA0215CB6A12CB1FCB3F226EB39458CF17019132E201C901FB00000A10293335300010104510344033F009000D570C8CB01C9D0802012017180021081BA50C1B5C0838343E903E8034CFCC200017321400F3C5807E80B2CFF26000513B513434FFFE900835D2708027DFC07E9035353D0134CFCC0415C415B80C1C1B5B5B5B490415C415A0002B01B232FFD40173C59400F3C5B3333D0032CFF27B55200201201D1E0201201F200013BBB39F008175F07F0068000DBA559F0086C718000DB8FCFF0085F03802012021220013B64A5E010204EBE0FA1001FBB461843AE9240F152118001E5C09BE010206EBE0FA1A60E038001E5CEA1E8086047AE140E68078001E5CEAB80111C344180012660F003C003060FE81CDF432CF190B19E2D93C060F0DBC06105E033E04883DCB11FB64DDC4964AD1BA06B879240DC23572F37CC5CAAAB143A2FFE03060FE81CDF432CF190B19E2D93C0610230004786D5045BF3F';

class DnsItem extends Contract {
/**
* @param provider
Expand All @@ -19,10 +19,10 @@ class DnsItem extends Contract {
super(provider, options);

this.methods.getData = this.getData.bind(this);
this.methods.getDomain = this.getDomain.bind(this);
this.methods.getAuctionInfo = this.getAuctionInfo.bind(this);
this.methods.getLastFillUpTime = this.getLastFillUpTime.bind(this);
this.methods.getDomain = this.getDomain.bind(this);
this.methods.dnsResolve = this.dnsResolve.bind(this);
this.methods.resolve = this.resolve.bind(this);
}

/**
Expand Down Expand Up @@ -115,13 +115,29 @@ class DnsItem extends Contract {

/**
* @param domain {string} e.g "sub.alice.ton"
* @param category {number}
* @returns {Promise<Cell|Address|null>}
* @param category? {string} category of requested DNS record, null for all categories
* @param oneStep? {boolean} non-recursive
* @returns {Promise<Map<String, Cell | Address | BN> | Cell | null>}
*/
async dnsResolve(domain, category) {
async resolve(domain, category, oneStep) {
const myAddress = await this.getAddress();
return DNS.resolve(this.provider, myAddress.toString(), domain, category, true);
return dnsResolve(this.provider, myAddress.toString(), domain, category, oneStep);
}
}

/**
* params {{category: string, value: Cell|null, queryId?: number}}
* @return {Cell}
*/
DnsItem.createChangeContentEntryBody = async (params) => {
const body = new Cell();
body.bits.writeUint(1234, 32); // OP
body.bits.writeUint(params.queryId || 0, 64); // query_id
body.bits.writeUint(await categoryToBN(params.category), 256);
if (params.value) {
body.refs[0] = params.value;
}
return body;
}

DnsItem.codeHex = DNS_ITEM_CODE_HEX;
Expand Down
Loading

0 comments on commit 5a0bc67

Please sign in to comment.