Tezos Domains for Developers #2: Buying & Updating Domains

Tezos Domains for Developers #2: Buying & Updating Domains

As part of our journey to bring Tezos Domains to mainnet, we are preparing a series of short articles covering how-tos and examples of integration. Our aim is to make the experience easier for developers starting with Tezos Domain.

All of the code in the series can be found in our dedicated repository. It contains the latest versions of our examples and includes instructions for running them.

Tezos Domains Client

Since our last article, there has been a breaking change: we renamed the @tezos-domains/client package to @tezos-domains/taquito-client, as we have added support for ConseilJS in addition to Taquito.

You can start by installing the required packages with your package manager of choice:

npm install @tezos-domains/taquito-client @tezos-domains/core @taquito/taquito

A basic typescript file that will get us started looks like this:

import { TezosToolkit } from '@taquito/taquito';
import { TaquitoTezosDomainsClient } from '@tezos-domains/taquito-client';
import { InMemorySigner } from '@taquito/signer';
import { generateNonce, RecordMetadata } from '@tezos-domains/core';

(async () => {
    const myAddress = 'tz1...';
    const mySigningKey = 'edsk...';

    const tezos = new TezosToolkit('https://delphinet-tezos.giganode.io/');
    tezos.setSignerProvider(await InMemorySigner.fromSecretKey(mySigningKey));
    const client = new TaquitoTezosDomainsClient({ tezos, network: 'delphinet' });
    // ...
})().catch(e => console.error(e));

As you can see, it defines an instance of TaquitoTezosDomainsClient connected to Delphinet and equipped with a signer.

You will need to supply your own account that has some balance on Delphinet and replace myAddress and mySigningKey values above. In-memory signer will work for the sake of this example, but in real-life DApps, you will always want to have proper signer support in place.

Buying a Domain

If a domain is available for registration, we can buy it programmatically. The DomainsManager instance available via the client will take care of this.

The Tezos Domains smart contracts use a commitment scheme to prevent snatching the desired domain from an interested buyer by front-running a transaction.

First, we need to create a commitment expressing an intent to buy a domain containing the label (alice), the new owner (our address), and a random nonce to prevent dictionary attacks on our commitment:

const label = 'alice';
const tld = 'delphi';
const nonce = generateNonce();

// First step of registering a domain - create a commitment for alice.delphi
const commitOperation = await client.manager.commit(tld, { label, owner: myAddress, nonce });
await commitOperation.confirmation();

After the commitment is confirmed, we can finally buy the domain. The following code will automatically call the smart contract and transfer the correct amount for 1-year ownership of the domain:

// One-year registration
const duration = 365;

// Show how much the registration costs
const info = await client.manager.getAcquisitionInfo(`${label}.${tld}`);
console.log(`Buying ${label}.${tld} for ${info.calculatePrice(duration)} mutez`);

// Reveal on blockchain and confirm the registration for specified duration in days
const buyOperation = await client.manager.buy(tld, { label, owner: myAddress, duration, address: myAddress, data: new RecordMetadata(), nonce });
await buyOperation.confirmation();

As you can guess, by supplying the address parameter to buy(), we will make the new domain alice.delphi resolve to myAddress.

The full source code is available in buy-domain.ts.

Creating a Subdomain

Now that the domain is ours, we can manage it using DomainsManager too. For example, we can add a new subdomain called pay.alice.delphi:

const subdomainLabel = 'pay';
const parent = 'alice.delphi';

const recordOperation = await client.manager.setChildRecord({ label: subdomainLabel, parent, owner: myAddress, address: myAddress, data: new RecordMetadata() });
await recordOperation.confirmation();

console.log(`Subdomain ${subdomainLabel}.${parent} has been created`);

Creating a Reverse Record

If we want our address to be resolvable back to the domain, we have to add a reverse record. Among other things, it will make the domain visible in the incoming transactions in other people’s wallets. Claiming a reverse record is easy:

const reverseRecordOperation = await client.manager.claimReverseRecord({ owner: myAddress, name: 'pay.alice.delphi', data: new RecordMetadata() });
await reverseRecordOperation.confirmation();

console.log(`Reverse record for ${myAddress} has been assigned to pay.alice.delphi`);

The full source code for this and above example is available in create-subdomain.ts.

Adding Metadata

Tezos Domains allows equipping domains with arbitrary additional data. One possibility is assigning some publicly visible OpenID claims to your domain. For example, we can equip alice.delphi with a name, a contact e-mail and a physical address:

let data = new RecordMetadata();
data.setJson('openid:name', 'Alice Smith');
data.setJson('openid:email', 'alice@smith.com');
data.setJson('openid:address', {
    street_address: '822  Hickory Street',
    locality: 'Huntsville',
    region: 'Illinois',
    country: 'United States'
});

const updateOperation = await client.manager.updateRecord({ name: 'alice.delphi', owner: myAddress, address: myAddress, data });
await updateOperation.confirmation();

As you can see, the setJson method accepts string and objects. In fact, anything serializable to JSON can be used as a metadata value. To keep the data usable by the rest of the world however, we will adhere to the OpenID definition of what the values should be.

The full source code is available in update-domain-with-data.ts.

Summary

We’ve shown how to buy and manipulate domains using the Tezos Domain client library. In the next article, we will focus on using the client to participate in domain auctions.

About the Team

The team at Agile Ventures has been working with Tezos since the early alphanet days. We have created two open-sourced projects focused on helping developers interact with the Tezos data and events easier and are hosting publicly available endpoints at TezosLive.io. Nowadays, we mostly focus on Tezos Domains.

7 Likes

Does your commitment scheme use a random nonce? Otherwise it’s feasible to enumerate most pronounceables combinations of ASCII chars and see which one hashes to the commitment being published.

3 Likes

Good call. We will need to update this.

The use of something like OpenID combined with selective privacy keys could allow for some powerful applications for automated agents, such as a “bonded escalation of trust,” where agent interactions can make claims, counterclaims and challenges subject to loss. There will be immense future applications where agents must interact at a high level of trust, exchanging, for instance, time/location ephemeral critical data, my favorite being autonomous mobility/drone traffic control, ephemeral map exchanges, perishable data sets, etc.

I’ve updated the post to include generating a random nonce. The nonce is now required by the smart contract and the client provides a helper function generating it.

Thanks goes to @murbard for catching this issue.