spec now at 1.0.0 release candidate

added domain freezing, suggest tld as domain receive rep, bug fixes
This commit is contained in:
stjet
2024-09-10 20:01:18 +00:00
parent 221af83c90
commit 998a621601
44 changed files with 195 additions and 86 deletions

7
LICENSE Normal file
View File

@@ -0,0 +1,7 @@
Copyright 2024 stjet/Prussia
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,5 @@
*Version 1.0.0 release-candidate*
Very similar to [Airtune's Banano NFT protocol](https://github.com/Airtune/73-meta-tokens)
In fact, though it is meant to be for domain names, it can actually be considered a sort of very limited NFT protocol.
@@ -69,13 +71,14 @@ Receives a Domain Transfer block. If not the opening block of the account, the r
- Subtype: send
- Link (send block hash): Hash of the Domain Transfer block
- Representative: Can *optionally* be the TLD account in order to make resolving backwards easier
## Domain Metadata block
To convey metadata associated with a block. Can only be sent by Domain Accounts
- Subtype: change
- Representative: Hash of the metadata
- Representative: Hash of the metadata (**cannot be all 1s, then it is Domain Freeze**)
> Currently, it is recommended that this metadata hash be a translated IPFS v0 Cid, so metadata files should be hosted on IPFS. IPFS is not mandated by the protocol, and it is perfectly acceptable to use something that is not IPFS to store metadata and use a regular SHA-256 hash of the file. However, clients will likely only support finding IPFS metadata.
@@ -87,12 +90,12 @@ To change the what address the domain resolves to
- Change in balance: 4224 raw
- Link (recepient): Banano address the domain should resolve to (typically the actual Banano address of the owner)
## Maybe: Domain Freeze block
## Domain Freeze block
All Domain Transfer blocks sent after this block are to be ignored. The domain becomes an "frozen domain". For a TLD account, prevents issuance of new domains for that TLD. For a Domain Account, prevents transfer of the domain currently held by it, as well as any change in resolving and metadata. Not the same as a burned domain for a Domain Account as frozen domains can still resolve to an address and have metadata, while burned domains cannot
- Subtype: change
- Representative: Pub key of all 0s
- Representative: Pub key (in hexadecimal) of "451", followed by sixty-two 1s
# Domain Metadata
@@ -127,6 +130,8 @@ To resolve a domain to a Domain Account (after checking the domain name for vali
The resolver should then go to the recipient of the Domain Transfer. If the opening block (height 1) is not a Domain Receive block for that Domain Transfer, then the resolver knows the domain has been burned, and the resolving process is over. The burned domain has no domain metadata or resolved address. If it does find the opening block is the Domain Receive block for that Domain Transfer, it should then crawl up the chain again, keeping note of any Domain Metadata or Domain Resolver blocks. Newer blocks replace the older ones. If it encounters a Domain Transfer block, it should discard the noted domain metadata and resolved address, and repeat. If it does not encounter a Domain Transfer block, and reaches the frontier (latest) block, then it should return the noted domain metadata and resolved address (or lack thereof).
Resolving backwards is also possible, but slightly more complicated. In the resolved address, look for any receives or pending transactions of 4242 raw in order to find Domain Accounts. If the resolver know what TLD address the domain is supposed to be, great. If not, try finding out by looking at the representative of the opening block (Domain Receive) of the found Domain Account. From the opening block's corresponding send (Domain Transfer), the resolver can find the domain name. Then, resolve like normal since the resolver now has the TLD address and domain name. After resolving, the resolver must check to make sure that the found domain account actually owns the domain.
## TLD (Issuing domains)
A TLD operator can use whatever system it wants for issuing domain names. Some ideas are taking payments or issuing based on certain criteria (eg, citizenship). It should not issue invalid domain names. Even if it does, clients will ignore them. TLDs should also refuse to send to Banano accounts that already have blocks, because otherwise the domain name will be burned, which is probably not what the purchaser of the domain wants.

View File

@@ -1,4 +1,5 @@
import * as util from "./util";
export * from "./constants";
import * as resolver from "./resolver";
import * as manager from "./manager";
import * as types from "./types";

View File

@@ -12,6 +12,9 @@
#main div {
max-width: 50vw;
}
.danger {
color: red;
}
@media only screen and (max-width: 900px) {
#main {
grid-template-columns: auto;
@@ -67,6 +70,8 @@
<br>
<button onclick="issue()">Issue domain</button>
<a id="issue-link"></a>
<br><br>
<button class="danger" onclick="freeze(true)">Freeze TLD</button>
</div>
<div id="domain">
<h2>Domain Account Manager</h2>
@@ -104,8 +109,8 @@
<br>
<button onclick="transfer()">Transfer domain</button>
<a id="transfer-link"></a>
<h3>Upload metadata to IPFS</h3>
//
<br><br>
<button class="danger" onclick="freeze(false)">Freeze domain</button>
</div>
</div>
<div id="resolver">
@@ -279,11 +284,16 @@
async function get_domain_account_domain() {
const resolver = new bns.Resolver(rpc2, tld_mapping);
domain_account_domain = resolver.resolve_backwards_ish(wallet.address, d.g("rc-tld").value);
domain_account_domain = await domain_account_domain;
domain_account_domain = await resolver.resolve_backwards_ish(wallet.address, d.g("rc-tld").value);
let frozen = false;
if (domain_account_domain.history[domain_account_domain.history.length - 1].type === "freeze") {
alert("This domain is frozen! That means you can't do anything with it.");
frozen = true;
}
const { name, resolved_address, metadata_hash } = domain_account_domain;
console.log(domain_account_domain);
d.g("found-name").textContent = name
d.g("found-name").textContent = name;
if (frozen) d.g("found-name").classList.add("danger");
d.g("found-address").textContent = resolved_address;
const cid_v0 = metadata_hash ? get_cid_v0_from_public_key(metadata_hash) : "none";
d.g("found-metadata").innerHTML = `${metadata_hash} (IPFS translation: <a href="https://ipfs.oversas.org/ipfs/${cid_v0}" target="_blank">${cid_v0}</a>)`;
@@ -308,6 +318,13 @@
d.g("transfer-link").href = `https://creeper.banano.cc/hash/${transfer_hash}`;
}
async function freeze(is_tld) {
if (await prompt(`Are you sure you want to freeze the ${ is_tld ? "TLD" : "domain" }? This will mean you can no longer transfer it, change the resolved address, or the metadata hash. Respond 'I am super sure' to proceed.`).trim() === "I am super sure") {
is_tld ? await tld_account.freeze() : await domain_account.freeze();
alert(`The ${ is_tld ? "TLD" : "domain" } should now be frozen`);
}
}
function seed_proceed() {
d.g("start-2").style.display = "none";
d.g("main").style.display = "grid";

8
constants.ts Normal file
View File

@@ -0,0 +1,8 @@
import { whole_to_raw, get_address_from_public_key } from "banani";
export const TRANS_MIN = whole_to_raw("0.0012070301");
export const TRANS_MAX = whole_to_raw("0.00120703011");
export const FREEZE_PUB_KEY = "451" + "1".repeat(61);
export const FREEZE_REP = get_address_from_public_key(FREEZE_PUB_KEY);

View File

@@ -1 +1 @@
window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA62ZXU/bMBSG/0uv2RcbjHEHTNvQ2IYAiQuEolPntLGaOpXtFKpp/31O0zZO7TiuncvW73mf468TO3n6O5L4KkfnozEwYHR0NFqAzNTveZGWOYp39f9vMznPVeOMsnR0/uloRHIQQsmkSN9Q8UZ5IGdQSUhG85QjG50/7cxvOV2CxJ+4uiCkKJlsOGujhmMo2+QPx2fd7H9HO+Dd7VUnQrUFmz5SmV0CmZULl32jCgcVfHbLiyVNkTtRmi4M9gh5jt0TUjeHWW+m8BJyYARbc0KZkk+ANCBD3GYen5wewvxBhSz46jIvyMyDqsuH4Pr1tREPwoSXA7u7jRiIflin1/oo8jWbFH7MjTKKdocEVW0a554LuaUfiHxflNx3I1miBsriIeMosiJPD01ED4zMZaGckEmQdOk9HnsxURk8Ip1m0o+800YRxaYyCj+oLo/jtgfOF29GhWXRW9IiKtg69Gq9ONydagkjWB4VS9dFkH4X93TKQJYce2maNoIofDsn4nvXtwh3ojDGV8xxCuopJXwWh6mOpXoDg1kq8Hrr60LpukBSuw78YTllfRW7K2bADLzqtztykGwOyyCYar9OmLzu64T3UyNVlz8l2kHkaqE9HerWPev3Xz5/ODk+xP6W44S+uiG1Jhy1LiIXef5QeXegWppI1CUISnphjSoS9wNE5gJV7ZGIG1WmyKq3S5osEniv9gleZcCm2Evd18aiy3HFcBJrSTjoUZ2duwjrtghrtfG/lYxIWrAugiYJB41B4MfjRBZJqcrPGXAOqwY42fjvoDZ5G37qeBulcYkylbwkMpmr2gBTTMbVnCTA0iRrbQUjh77QoHymKBOoC1Uy4cU8WZTjnJJkhq7hcEQFZ7GoX7lVHrWnQEx7crDGhGew60RtBvvPEHsO9qjBstD6eGAmWmRQNtWiqteYA9yIwhj46r0JDW0QUUV7Ew1tEJHDS+Xy0i6bBkyXBXGEuj5takJPKdlThtM2lagPtZEFcZrBr0anLsQOnk0+AFetPW+o0oYR5eTMe2ma4iDmEjmdrPxWjaGNIVbrAlOPBWTVB5HXO6saM7XTHEBddgDnWb9DF3OgrPMjU6vZ+KbR5fNLpTe1fYaxqVyudyiKfGlz2ra4oh9uvnZ2rGnzc+jskiHpHyXrfbJuMq6QRnD36z2tvd/mF0pIQYLDaSvpN6tfWNvfi7QUPlb7M27xsk29zeyBAxMTp9lW4jnwxgVJb7Oe8TWfmz/fm/AlcFq94hfv1N/tyI960PbwqnY5oWmyfG+rB4Zovxrs3SdOzpxPCk3gMqJTvxOKReewrTtQyR2nWkPkMEyRFCkm6XqmEgZzaw03VQ5LZD6WpsphuTky1oNvc2sJDKPn/7j8/9qZIAAA"
window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA62ZYXPaOBCG/wuf02ubXnq5fAspuWaapAzhJu11Oh4hL1iDkRlJJqE3999PxgbLSJaF5I/Jvvs+K3m9RvaPfwcCXsXgajBDFFEyOBuskUjk36sszlPgb8v//5aIVSqDS0LjwdXvZwOcIs6lTPD4DeFvpAcwigoJTkgaM6CDqx8H8zEjGyTgC2yvMc5yKmrOzqjmaMom+f35ZTv7v7MDcDK+aUXImLfpMxHJEOFlvrbZ1yp/UMaWY5ZtSAzMilJ0frBnlKbQfkHKsJ91dQmHKEUUQ+OaECrlc4RrkCZuMs8vPp7C/Ey4yNh2mGZ46UBV5X1w3dZai3thopcTl7vP6Il+2qJ3+iDyHZ1nbsxKGUSbAAY5m2apYyM39D2Rn7Kcud5IhqyeqpgmDHiSpfGphaiJgbWspRNQgQTZOO/HUU5QBc9AFolwIx+0QUReTUbuBlXlYdzmxrni9Sy/KjpHWsAE26Xe7JrDvqiGMIDlMLFUXQDpMXsiC4pEzqCTpmgDiNx1cTx8dV1NeBD5MT5BCgskn1LcpTl0dSjVGejNkol3e18bStV5kppz4CtNCe2a2G05PVbgNL/tmb1Uc1oF3lTzcULntR8nnJ8asTz8SdEBIrZr5elQRo+s3/35x/uL81Psxwzm5NUOKTX+qN0QuU7TaeHdgmpoAlFDxAnuhNWqQNxnxBMbqIgHIu7lmMLbziUpskDgk7xP4CZBdAGd1GNtKDqfFQwrsZT4g57lb+c2wi4WYC1v/NucYkEy2kZQJP6gGeLw4TwSWZTL8XOJGEPbGjiv/A9Qk7wJ/2h5G6VwsTQVLMciWsnZgBYQzYprEiEaR0njVtBq6Er1qmcBIkLloIrmLFtF63yWEhwtwbYdlizvKtblK7fCo/TkAHFHDcYc/woOiyjN0PEzxFyDOau3KpQ1nliJkulVTdFUZY9ZwLXIjwGvzjehpvUiymxnoqb1IjL0Uri8NMemBlNlXhwuj0/VTOgYJUdKf1o1ibpQlcyLU29+sTvlILbwTPIeuLL3nKFS60cU80vn1tTFXswNMDLfunWNpg0hFn0BsUMDGfVe5N2dVeyZvNMsQFV2AueneobOVojQ1o9MjbD2TaPN50GWtzB9hjGpbK4T4Fm6MTntI7bs6f2n1oXVMTeH1iVpku5dMp4ny5B2hNSS21/vKfFum1sG8Mv8JkMVdBs9gEAxEshitZd0m5Vvvm1lVQoXq+PWMXiZeshkNmWI8rnVbC9xvILaSUuNGQ8Lis/tZDT6ZxSN/x5GX0bfa6cNYqT4bMDfNhVNvw8Gq8lobLGRUYvF/de/TLny35ak6eT68Sl6uP5mSj0Euw3uHi0Gd48Wg/2pQI5PTOJo8840aDXR8Zg9OqhdXFofwYrAZkQWbj/9DDqLbbmAQm45Lmgii2EMOIshinedG1G0Mj4cdZXFEqiLpa6yWFa/xcvNN7k1BJrRz/8Bki4U8PIhAAA="

View File

@@ -1 +1 @@
window.searchData = "data:application/octet-stream;base64,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";
window.searchData = "data:application/octet-stream;base64,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";

File diff suppressed because one or more lines are too long

View File

@@ -12,6 +12,9 @@
#main div {
max-width: 50vw;
}
.danger {
color: red;
}
@media only screen and (max-width: 900px) {
#main {
grid-template-columns: auto;
@@ -67,6 +70,8 @@
<br>
<button onclick="issue()">Issue domain</button>
<a id="issue-link"></a>
<br><br>
<button class="danger" onclick="freeze(true)">Freeze TLD</button>
</div>
<div id="domain">
<h2>Domain Account Manager</h2>
@@ -104,8 +109,8 @@
<br>
<button onclick="transfer()">Transfer domain</button>
<a id="transfer-link"></a>
<h3>Upload metadata to IPFS</h3>
//
<br><br>
<button class="danger" onclick="freeze(false)">Freeze domain</button>
</div>
</div>
<div id="resolver">
@@ -279,11 +284,16 @@
async function get_domain_account_domain() {
const resolver = new bns.Resolver(rpc2, tld_mapping);
domain_account_domain = resolver.resolve_backwards_ish(wallet.address, d.g("rc-tld").value);
domain_account_domain = await domain_account_domain;
domain_account_domain = await resolver.resolve_backwards_ish(wallet.address, d.g("rc-tld").value);
let frozen = false;
if (domain_account_domain.history[domain_account_domain.history.length - 1].type === "freeze") {
alert("This domain is frozen! That means you can't do anything with it.");
frozen = true;
}
const { name, resolved_address, metadata_hash } = domain_account_domain;
console.log(domain_account_domain);
d.g("found-name").textContent = name
d.g("found-name").textContent = name;
if (frozen) d.g("found-name").classList.add("danger");
d.g("found-address").textContent = resolved_address;
const cid_v0 = metadata_hash ? get_cid_v0_from_public_key(metadata_hash) : "none";
d.g("found-metadata").innerHTML = `${metadata_hash} (IPFS translation: <a href="https://ipfs.oversas.org/ipfs/${cid_v0}" target="_blank">${cid_v0}</a>)`;
@@ -308,6 +318,13 @@
d.g("transfer-link").href = `https://creeper.banano.cc/hash/${transfer_hash}`;
}
async function freeze(is_tld) {
if (await prompt(`Are you sure you want to freeze the ${ is_tld ? "TLD" : "domain" }? This will mean you can no longer transfer it, change the resolved address, or the metadata hash. Respond 'I am super sure' to proceed.`).trim() === "I am super sure") {
is_tld ? await tld_account.freeze() : await domain_account.freeze();
alert(`The ${ is_tld ? "TLD" : "domain" } should now be frozen`);
}
}
function seed_proceed() {
d.g("start-2").style.display = "none";
d.g("main").style.display = "grid";

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -6,12 +6,17 @@
<a href="classes/TLDAccountManager.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-128"></use></svg><span>TLDAccount<wbr/>Manager</span></a>
</div></section><section class="tsd-index-section"><h3 class="tsd-index-heading">Interfaces</h3><div class="tsd-index-list"><a href="interfaces/Domain.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-256"></use></svg><span>Domain</span></a>
<a href="interfaces/DomainBlock.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-256"></use></svg><span>Domain<wbr/>Block</span></a>
<a href="interfaces/DomainFreeze.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-256"></use></svg><span>Domain<wbr/>Freeze</span></a>
<a href="interfaces/DomainMetadata.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-256"></use></svg><span>Domain<wbr/>Metadata</span></a>
<a href="interfaces/DomainReceive.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-256"></use></svg><span>Domain<wbr/>Receive</span></a>
<a href="interfaces/DomainResolver.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-256"></use></svg><span>Domain<wbr/>Resolver</span></a>
<a href="interfaces/DomainTransfer.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-256"></use></svg><span>Domain<wbr/>Transfer</span></a>
</div></section><section class="tsd-index-section"><h3 class="tsd-index-heading">Type Aliases</h3><div class="tsd-index-list"><a href="types/DomainBlocks.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-2097152"></use></svg><span>Domain<wbr/>Blocks</span></a>
</div></section><section class="tsd-index-section"><h3 class="tsd-index-heading">Variables</h3><div class="tsd-index-list"><a href="variables/LOG.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-32"></use></svg><span>LOG</span></a>
</div></section><section class="tsd-index-section"><h3 class="tsd-index-heading">Variables</h3><div class="tsd-index-list"><a href="variables/FREEZE_PUB_KEY.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-32"></use></svg><span>FREEZE_<wbr/>PUB_<wbr/>KEY</span></a>
<a href="variables/FREEZE_REP.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-32"></use></svg><span>FREEZE_<wbr/>REP</span></a>
<a href="variables/LOG.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-32"></use></svg><span>LOG</span></a>
<a href="variables/TRANS_MAX.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-32"></use></svg><span>TRANS_<wbr/>MAX</span></a>
<a href="variables/TRANS_MIN.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-32"></use></svg><span>TRANS_<wbr/>MIN</span></a>
</div></section><section class="tsd-index-section"><h3 class="tsd-index-heading">Functions</h3><div class="tsd-index-list"><a href="functions/address_to_cid_v0.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-64"></use></svg><span>address_<wbr/>to_<wbr/>cid_<wbr/>v0</span></a>
<a href="functions/base58_to_hex.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-64"></use></svg><span>base58_<wbr/>to_<wbr/>hex</span></a>
<a href="functions/bigint_to_uint8array.html" class="tsd-index-link"><svg class="tsd-kind-icon" viewBox="0 0 24 24"><use href="assets/icons.svg#icon-64"></use></svg><span>bigint_<wbr/>to_<wbr/>uint8array</span></a>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,5 @@
export * from "./util";
export * from "./constants";
export * from "./resolver";
export * from "./manager";
export * from "./types";

View File

@@ -4,6 +4,7 @@ import { get_address_from_public_key, raw_to_whole, whole_to_raw, Wallet } from
import type { Domain } from "./types";
import { DomainAccount, TLDAccount } from "./resolver";
import { decode_domain_name, encode_domain_name, LOG } from "./util";
import { TRANS_MAX, TRANS_MIN, FREEZE_REP, FREEZE_PUB_KEY } from "./constants";
export class TLDAccountManager extends TLDAccount {
wallet: Wallet;
@@ -22,6 +23,11 @@ export class TLDAccountManager extends TLDAccount {
return block_hash;
}
async freeze() {
await this.wallet.change_representative(FREEZE_REP);
//
}
//ideally tld starts out with say, 100 Banano to open with, and never needs to receive anything ever again. 100 Banano is over for over 80k domain issuances.
async receive() {
//up to 20, technically
@@ -39,7 +45,7 @@ export class DomainAccountManager extends DomainAccount {
this.domain = domain;
}
async receive_domain(receive_hash: string, allow_burning?: boolean) {
async receive_domain(receive_hash: string, tld?: Address, allow_burning?: boolean) {
let burning = false;
const { history } = await this.rpc.get_account_history(this.address, 1);
if (history.length > 1 && !allow_burning) {
@@ -47,26 +53,23 @@ export class DomainAccountManager extends DomainAccount {
throw new Error("`allow_burning` must be true in order to receive this domain");
}
const block_info = await this.rpc.get_block_info(receive_hash);
const min = whole_to_raw("0.0012070301");
const max = whole_to_raw("0.00120703011");
const amount = BigInt(block_info.amount);
if (amount < min || amount > max) throw new Error("`receive_hash` is not a Domain Transfer block");
await this.wallet.receive(receive_hash);
if (amount < TRANS_MIN || amount > TRANS_MAX) throw new Error("`receive_hash` is not a Domain Transfer block");
await this.wallet.receive(receive_hash, undefined, tld);
//
}
async transfer_domain(domain_name: string, to: Address): Promise<string> {
const balance = (await this.wallet.get_account_info()).balance;
const min = whole_to_raw("0.0012070301");
const max = whole_to_raw("0.00120703011");
let send_amount = raw_to_whole(max);
if (max > BigInt(balance) && min <= BigInt(balance)) send_amount = raw_to_whole(BigInt(balance));
let send_amount = raw_to_whole(TRANS_MAX);
if (TRANS_MAX > BigInt(balance) && TRANS_MIN <= BigInt(balance)) send_amount = raw_to_whole(BigInt(balance));
const block_hash = await this.wallet.send(to, send_amount, undefined, get_address_from_public_key(encode_domain_name(domain_name)));
//
return block_hash;
}
async declare_domain_metadata(metadata_hash: string) {
if (metadata_hash === FREEZE_PUB_KEY) throw new Error("A metadata hash of all 1s freezes the domain");
await this.wallet.change_representative(get_address_from_public_key(metadata_hash));
//
}
@@ -75,5 +78,10 @@ export class DomainAccountManager extends DomainAccount {
await this.wallet.send(address, raw_to_whole(4224n));
//
}
async freeze() {
await this.wallet.change_representative(FREEZE_REP);
//
}
}

View File

@@ -13,6 +13,8 @@ import * as crypto from "crypto";
let tld_wallet = new bns.banani.Wallet(rpc, test_seed);
console.log(await new bns.Resolver(rpc2, { "test": tld_wallet.address }).resolve("chicken", "test")); //freeze test
console.log(await new bns.Resolver(rpc2, { "test": tld_wallet.address }).resolve_backwards_ish("ban_1119d44eg3fey3mxpk8mshn7gf5dfzsuiaz1ypoh5nqy8bxbao54zzc5rnka", "test"));
let tld = new bns.TLDAccountManager(rpc, tld_wallet);
@@ -21,7 +23,7 @@ import * as crypto from "crypto";
const rand_wallet = bns.banani.Wallet.gen_random_wallet(rpc);
const rand_name = `test${String(Math.random()).replaceAll(".", "")}`;
const rand_name = `rc-test${String(Math.random()).replaceAll(".", "")}`;
const issue_hash = await tld.issue_domain_name(rand_name, rand_wallet.address);
@@ -31,7 +33,7 @@ import * as crypto from "crypto";
await rand_dam.declare_domain_resolve_to("ban_3346kkobb11qqpo17imgiybmwrgibr7yi34mwn5j6uywyke8f7fnfp94uyps");
await rand_dam.declare_domain_metadata("1".repeat(64));
await rand_dam.declare_domain_metadata("6".repeat(64));
await rand_dam.declare_domain_resolve_to("ban_1burnbabyburndiscoinferno111111111111111111111111111aj49sw3w");
@@ -43,7 +45,25 @@ import * as crypto from "crypto";
await rand_dam2.receive_domain(transfer_hash);
await rand_dam2.declare_domain_metadata("0".repeat(64));
await rand_dam2.declare_domain_metadata("2".repeat(64));
/*
//freeze test
await rand_dam2.freeze();
const rand_wallet3 = bns.banani.Wallet.gen_random_wallet(rpc);
console.log(rand_wallet3.seed);
const transfer_hash2 = await rand_dam2.transfer_domain(rand_name, rand_wallet3.address);
const rand_dam3 = new bns.DomainAccountManager(rpc, rand_wallet3);
await rand_dam3.receive_domain(transfer_hash2);
await rand_dam3.declare_domain_metadata("4".repeat(64));
await rand_dam3.declare_domain_resolve_to("ban_3fzpw7pb9xt64qhwi47oa47x9zj713fkshntdk5y7khmn54n18szb7ymybdt");
*/
//await rand_dam2.declare_domain_resolve_to("ban_1o7ija3mdbmpzt8qfnck583tn99fiupgbyzxtbk5h4g6j57a7rawge6yzxqp");

View File

@@ -1,6 +1,6 @@
{
"name": "banani-bns",
"version": "0.0.2",
"version": "0.0.3",
"description": "JS/TS library for the Banano cryptocurrency's currently unofficial Banano Name System (BNS)",
"main": "main.js",
"scripts": {

View File

@@ -1,10 +1,9 @@
import type { RPC } from "banani";
import type { Address, AccountHistoryRawRPC, RPC } from "banani";
import { get_address_from_public_key, get_public_key_from_address, whole_to_raw } from "banani";
import type { Address, AccountHistoryRawRPC } from "banani";
import type { Domain, DomainTransfer } from "./types";
import { decode_domain_name, encode_domain_name, LOG } from "./util";
import { FREEZE_REP, TRANS_MAX, TRANS_MIN } from "./constants";
class Account {
readonly rpc: RPC;
@@ -27,6 +26,8 @@ class Account {
}
}
export class TLDAccount extends Account {
all_issued: Domain[];
@@ -42,9 +43,7 @@ export class TLDAccount extends Account {
const { history } = await this.get_history_from_open(head_hash, 100);
for (const block of history) {
const amount = BigInt(block.amount ?? 0); //no amount if is change rep only
const min = whole_to_raw("0.0012070301");
const max = whole_to_raw("0.00120703011");
if (amount >= min && amount <= max) {
if (block.subtype === "send" && amount >= TRANS_MIN && amount <= TRANS_MAX) {
const found_name = decode_domain_name(get_public_key_from_address(block.representative));
//if already in issued, this one is invalid
if (name === found_name) {
@@ -61,7 +60,8 @@ export class TLDAccount extends Account {
};
}
}
if (block.hash === frontier_hash) {
//again, no else if because of block.hash === frontier_hash
if ((block.representative === FREEZE_REP && block.subtype === "change") || (block.hash === frontier_hash)) {
return;
}
}
@@ -77,9 +77,7 @@ export class TLDAccount extends Account {
const { history } = await this.get_history_from_open(head_hash, 100);
for (const block of history) {
const amount = BigInt(block.amount ?? 0); //no amount if change rep only
const min = whole_to_raw("0.0012070301");
const max = whole_to_raw("0.00120703011");
if (block.subtype === "send" && amount >= min && amount <= max) {
if (block.subtype === "send" && amount >= TRANS_MIN && amount <= TRANS_MAX) {
const name = decode_domain_name(get_public_key_from_address(block.representative));
//if already in issued, this one is invalid
if (!issued[name]) {
@@ -97,12 +95,13 @@ export class TLDAccount extends Account {
} else if (LOG) {
console.log(`"${name}" already issued but TLD tried to issue again. Invalid.`);
}
if (block.hash === frontier_hash) {
}
//cannot be "else if" because of the block.hash === frontier_hash thing
if ((block.representative === FREEZE_REP && block.subtype === "change") || (block.hash === frontier_hash)) {
this.all_issued = Object.values(issued);
return this.all_issued;
}
}
}
head_hash = history[history.length - 1].hash;
}
}
@@ -131,8 +130,6 @@ export class DomainAccount extends Account {
const { history } = await this.get_history_from_open(head_hash, 1000) as AccountHistoryRawRPC;
for (const block of history) {
const amount = BigInt(block.amount ?? 0); //amount is 0 if change rep only, apparently
const min = whole_to_raw("0.0012070301");
const max = whole_to_raw("0.00120703011");
if (block.height === "1") {
//domain burned due to not being received as the opening block
//? is in case fake domain
@@ -146,7 +143,7 @@ export class DomainAccount extends Account {
type: "receive",
block,
});
} else if (block.subtype === "send" && amount >= min && amount <= max) {
} else if (block.subtype === "send" && amount >= TRANS_MIN && amount <= TRANS_MAX) {
const name = decode_domain_name(get_public_key_from_address(block.representative));
if (this.domain.name === name) {
//domain is transferred away, this domain account no longer owns it
@@ -160,6 +157,12 @@ export class DomainAccount extends Account {
});
return this.domain;
}
} else if (block.subtype === "change" && block.representative === FREEZE_REP) {
this.domain.history.push({
type: "freeze",
block,
});
return this.domain;
} else if (block.subtype === "change") {
this.domain.metadata_hash = get_public_key_from_address(block.representative);
this.domain.history.push({
@@ -167,7 +170,6 @@ export class DomainAccount extends Account {
block,
metadata_hash: this.domain.metadata_hash,
});
//
} else if (block.subtype === "send" && amount === 4224n) {
this.domain.resolved_address = get_address_from_public_key(block.link);
this.domain.history.push({
@@ -214,7 +216,8 @@ export class Resolver {
const transfer_block = await this.rpc.get_block_info(transfer_hash);
const domain_name = decode_domain_name(get_public_key_from_address(transfer_block.contents.representative));
let domain = await this.resolve(domain_name, tld);
const last_transfer = domain.history.reverse().find((b): b is DomainTransfer => b.type === "transfer");
//.reverse() mutates the original array, evil bastards!
const last_transfer = domain?.history.slice().reverse().find((b): b is DomainTransfer => b.type === "transfer");
if (last_transfer.to === domain_account_address) return domain;
}
}

View File

@@ -1,7 +1,7 @@
import type { Address, AccountHistoryRawBlock } from "banani";
export interface DomainBlock {
type: string;
type: "transfer" | "receive" | "metadata" | "resolver" | "freeze";
block: AccountHistoryRawBlock;
}
@@ -24,7 +24,11 @@ export interface DomainResolver extends DomainBlock {
resolved_address: Address;
}
export type DomainBlocks = DomainTransfer | DomainReceive | DomainMetadata | DomainResolver;
export interface DomainFreeze extends DomainBlock {
type: "freeze";
}
export type DomainBlocks = DomainTransfer | DomainReceive | DomainMetadata | DomainResolver | DomainFreeze;
export interface Domain {
tld: Address;

View File

@@ -52,10 +52,12 @@ export function base58_to_hex(base58: string): string {
return uint8array_to_hex(bigint_to_uint8array(bint, 34));
}
/** IPFS CID v0 to Banano address */
export function cid_v0_to_address(cid_v0: string): Address {
return get_address_from_public_key(base58_to_hex(cid_v0).slice(4));
}
/** Banano address to IPFS CID v0 */
export function address_to_cid_v0(address: Address): string {
return hex_to_base58("1220" + get_public_key_from_address(address));
}