Tokenizing Real-World Assets

This guide shows how to create a non-fungible token (NFT) that represents a real-world asset — like a document, a product, or a right of ownership — on the Keeta Network.

1

Prepare your accounts

You'll need two accounts:

  • A signer account to send the transaction

  • An authority account to sign the metadata (can be the same in testing)

const signer = KeetaNet.lib.Account.fromSeed(DEMO_SEED, 0);
const authority = KeetaNet.lib.Account.fromSeed(DEMO_SEED, 1);
2

Create metadata for your real-world asset

This includes:

  • A unique ID for the asset (e.g. serial number, URL, or database ref)

  • A digital signature proving the authority account approved it

const assetIdBuffer = Buffer.from(ASSET_ID, 'utf-8');
const signatureBuffer = await authority.sign(assetIdBuffer);

const metadata = {
  asset_id: ASSET_ID,
  authority: authority.publicKeyString.get(),
  signature: signatureBuffer.toString('base64')
};

const metadataBase64 = Buffer.from(JSON.stringify(metadata)).toString('base64');
3

Start a transaction builder

This prepares your transaction to include all operations in one publishable bundle.

const builder = client.initBuilder();
builder.updateAccounts({
  signer,
  account: signer
});
4

Create the token account

This is where the NFT will live. It’s a new account of type TOKEN.

const token = builder.generateIdentifier(KeetaNet.lib.Account.AccountKeyAlgorithm.TOKEN);
await client.computeBuilderBlocks(builder); // seal block so token exists
5

Make it non-fungible

Set the token’s supply to 1. That means only one account can own this NFT at a time.

builder.modifyTokenSupply(1n, { account: token.account });
6

Attach metadata and permissions

Now link your signed metadata to the token, and set permissions so it can be held by any user.

builder.setInfo({
  name: 'RWA-DEMO',
  description: 'Token representing a real-world asset',
  metadata: metadataBase64,
  defaultPermission: new KeetaNet.lib.Permissions(['ACCESS'], [])
}, {
  account: token.account
});
7

Publish the transaction

Finalize and submit your transaction to the Keeta Network.

await client.computeBuilderBlocks(builder);
await client.publishBuilder(builder);

Your NFT now lives on-chain and holds signed, verifiable metadata that links it to a real-world asset.

To see its address:

console.log('Token address:', token.account.publicKeyString.get());

Full Code Example

const KeetaNet = require('@keetanetwork/keetanet-client');

const DEMO_SEED = 'D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0';
const ASSET_ID = 'asset://unique-asset-id-001';

async function main() {
  // 1️⃣ Create two accounts from the seed:
  // - signer: sends the transaction
  // - authority: signs the metadata (can be same as signer for demo)
  const signer = KeetaNet.lib.Account.fromSeed(DEMO_SEED, 0);
  const authority = KeetaNet.lib.Account.fromSeed(DEMO_SEED, 1);

  // 2️⃣ Connect to the Keeta test network using the signer account
  const client = KeetaNet.UserClient.fromNetwork('test', signer);

  // 3️⃣ Create and sign the asset metadata
  const assetIdBuffer = Buffer.from(ASSET_ID, 'utf-8');
  const signatureBuffer = await authority.sign(assetIdBuffer);

  const metadata = {
    asset_id: ASSET_ID,
    authority: authority.publicKeyString.get(),
    signature: signatureBuffer.toString('base64')
  };

  const metadataBase64 = Buffer.from(JSON.stringify(metadata)).toString('base64');

  // 4️⃣ Start building a transaction
  const builder = client.initBuilder();
  builder.updateAccounts({
    signer,
    account: signer
  });

  // 5️⃣ Generate a new token account (this will be your NFT)
  const token = builder.generateIdentifier(KeetaNet.lib.Account.AccountKeyAlgorithm.TOKEN);

  // 6️⃣ Compute a block to seal the token creation (required before you can modify it)
  await client.computeBuilderBlocks(builder);

  // 7️⃣ Set the token supply to 1 — making it a non-fungible token
  builder.modifyTokenSupply(1n, {
    account: token.account
  });

  // 8️⃣ Attach the metadata and set default permissions (allow others to hold it)
  builder.setInfo({
    name: 'RWA-DEMO',
    description: 'Non-Fungible Token representing a real-world asset',
    metadata: metadataBase64,
    defaultPermission: new KeetaNet.lib.Permissions(['ACCESS'], [])
  }, {
    account: token.account
  });

  // 9️⃣ Compute and publish all blocks to the network
  await client.computeBuilderBlocks(builder);
  await client.publishBuilder(builder);

  // 🔚 Done — log the token's public address
  console.log('✅ RWA Token created at:', token.account.publicKeyString.get());
}

main().catch(console.error);

Last updated