# Table of Contents - [Introduction | Keeta Network](#introduction-keeta-network) - [Start Developing | Keeta Network](#start-developing-keeta-network) - [Create Your First Account | Keeta Network](#create-your-first-account-keeta-network) - [Consensus | Keeta Network](#consensus-keeta-network) - [Data Structure | Keeta Network](#data-structure-keeta-network) - [Create a Block | Keeta Network](#create-a-block-keeta-network) - [Send a Transaction | Keeta Network](#send-a-transaction-keeta-network) - [Vote Stapling | Keeta Network](#vote-stapling-keeta-network) - [Voting Power | Keeta Network](#voting-power-keeta-network) - [Votes | Keeta Network](#votes-keeta-network) - [Blocks | Keeta Network](#blocks-keeta-network) - [Ledger | Keeta Network](#ledger-keeta-network) - [Get Ledger History | Keeta Network](#get-ledger-history-keeta-network) - [Ledger Pruning | Keeta Network](#ledger-pruning-keeta-network) - [Nodes | Keeta Network](#nodes-keeta-network) - [Send | Keeta Network](#send-keeta-network) - [Data Integrity | Keeta Network](#data-integrity-keeta-network) - [Accounts | Keeta Network](#accounts-keeta-network) - [Storing Key Pairs | Keeta Network](#storing-key-pairs-keeta-network) - [Post Quantum Readiness | Keeta Network](#post-quantum-readiness-keeta-network) - [Native Tokenization | Keeta Network](#native-tokenization-keeta-network) - [Key Pairs | Keeta Network](#key-pairs-keeta-network) - [Protection From Common Attacks | Keeta Network](#protection-from-common-attacks-keeta-network) - [Separating Nodes from Hardware | Keeta Network](#separating-nodes-from-hardware-keeta-network) - [Digital Signatures | Keeta Network](#digital-signatures-keeta-network) - [Storage Accounts | Keeta Network](#storage-accounts-keeta-network) - [Benchmarks and Performance Metrics | Keeta Network](#benchmarks-and-performance-metrics-keeta-network) - [Certificates | Keeta Network](#certificates-keeta-network) - [Get Certificates | Keeta Network](#get-certificates-keeta-network) - [Identity Profiles | Keeta Network](#identity-profiles-keeta-network) - [Creating an Anchor | Keeta Network](#creating-an-anchor-keeta-network) - [Permissions | Keeta Network](#permissions-keeta-network) - [Eliminating Mempools | Keeta Network](#eliminating-mempools-keeta-network) - [Anchors | Keeta Network](#anchors-keeta-network) - [Operations | Keeta Network](#operations-keeta-network) - [Set Permissions | Keeta Network](#set-permissions-keeta-network) - [setInfo | Keeta Network](#setinfo-keeta-network) - [Built-in Rules Engine | Keeta Network](#built-in-rules-engine-keeta-network) - [updatePermissions | Keeta Network](#updatepermissions-keeta-network) - [Keeta Network's Advantage | Keeta Network](#keeta-network-s-advantage-keeta-network) - [Receive | Keeta Network](#receive-keeta-network) - [Public Network | Keeta Network](#public-network-keeta-network) - [Tokenomics | Keeta Network](#tokenomics-keeta-network) - [Private Sub Network | Keeta Network](#private-sub-network-keeta-network) - [modifyTokenBalance | Keeta Network](#modifytokenbalance-keeta-network) - [Roadmap | Keeta Network](#roadmap-keeta-network) - [modifyTokenSupply | Keeta Network](#modifytokensupply-keeta-network) - [Token Creation | Keeta Network](#token-creation-keeta-network) - [Resolving the Blockchain Trilemma | Keeta Network](#resolving-the-blockchain-trilemma-keeta-network) - [Official Links | Keeta Network](#official-links-keeta-network) - [Articles | Keeta Network](#articles-keeta-network) - [Utilizing Identity Profiles | Keeta Network](#utilizing-identity-profiles-keeta-network) - [Burn Tokens | Keeta Network](#burn-tokens-keeta-network) - [Cryptographically Verifiable Identity Sharing with Keeta | Keeta Network](#cryptographically-verifiable-identity-sharing-with-keeta-keeta-network) - [Mint Tokens | Keeta Network](#mint-tokens-keeta-network) - [Single-Token Storage Account | Keeta Network](#single-token-storage-account-keeta-network) - [Deploying a Node | Keeta Network](#deploying-a-node-keeta-network) - [Tokenizing Real-World Assets | Keeta Network](#tokenizing-real-world-assets-keeta-network) - [Create a Storage Account | Keeta Network](#create-a-storage-account-keeta-network) - [Email Protection | Cloudflare](#email-protection-cloudflare) - [generateIdentifier | Keeta Network](#generateidentifier-keeta-network) --- # Introduction | Keeta Network Keeta Network is a high-performance layer-1 blockchain network designed to serve as a common-ground for all asset transfers. Cross-chain transactions can be completed seamless, providing a direct transfer between any assets from any network, instantly. Systems can easily connect to Keeta Network, allowing their assets to interact with the rest of the assets in Keeta's ecosystem. In addition to interoperability, Keeta has also introduced unprecedented performance and utility. Settlement times of 400 milliseconds and a throughput of up to 10 million transactions per second place Keeta as the front-runner in efficiency. This performance and innovation, in addition to Keeta's native tokenization and built-in compliance protocols, makes Keeta Network the ideal centerpiece for the digital asset ecosystem. [](https://docs.keeta.com/introduction/start-developing) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FHgY49P2KrE8fvfMRmNHn%252Fdev.png%3Falt%3Dmedia%26token%3D3e7e484c-3852-4c22-a809-29bfcdebdd6f&width=490&dpr=4&quality=100&sign=9dab14c7&sv=2) **Start Developing** [](https://docs.keeta.com/introduction/create-your-first-account) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FweQ3ROX1bSRp3Y9jXi5T%252Faccount.png%3Falt%3Dmedia%26token%3Dbe4b3575-e062-4b83-b55a-298769af2c42&width=490&dpr=4&quality=100&sign=47dca75c&sv=2) **Create your first account** [](https://docs.keeta.com/introduction/send-a-transaction) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FIJYk6VY0isQoWJwkEPHF%252Fsend.png%3Falt%3Dmedia%26token%3D1bcacda6-e3e7-4538-a878-6dd2005c3ae7&width=490&dpr=4&quality=100&sign=1c001479&sv=2) **Send a transaction** ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2FpitcpcamWc0BKEe28I1D%2Fblobs%2Frol3J9lf9kZjGv4gqdBr%2Fimage.png&width=768&dpr=4&quality=100&sign=67c9fa1f&sv=2) Keeta Network connecting a variety of networks to create an interconnected digital ecosystem. Last updated 7 months ago --- # Start Developing | Keeta Network To interact with the Keeta Network, we’ve built the **KeetaNet SDK** — a JavaScript and TypeScript-compatible library that works in multiple environments, including **Node.js**, modern **web browsers**, and other JavaScript runtimes. Whether you're building server-side applications or browser-based dApps, the SDK gives you everything you need to connect to the Keeta Network, manage accounts, send transactions, and more. [hashtag](https://docs.keeta.com/introduction/start-developing#installation-and-type-support) Installation and Type Support -------------------------------------------------------------------------------------------------------------------------------- The SDK includes full TypeScript definitions, so you’ll get autocomplete and inline type checking in modern editors. You can install it from npm: Copy npm install @keetanetwork/keetanet-client Type definitions are bundled with the package — no need to install anything extra. [hashtag](https://docs.keeta.com/introduction/start-developing#using-the-sdk-in-nodejs) Using the SDK in NodeJS -------------------------------------------------------------------------------------------------------------------- In Node.js, you can import the KeetaNet SDK like this: Copy import * as KeetaNet from '@keetanetwork/keetanet-client'; Once imported, the SDK exposes several modules and utilities. The most important starting point is the `UserClient`, which lets you connect to the network and perform operations like sending tokens or fetching blockchain data. Copy const signer = KeetaNet.lib.Account.fromSeed(mySeed, 0); const client = KeetaNet.UserClient.fromNetwork('test', signer); [hashtag](https://docs.keeta.com/introduction/start-developing#using-the-sdk-in-the-browser) Using the SDK in the Browser ------------------------------------------------------------------------------------------------------------------------------ You can also use the KeetaNet SDK directly in a browser using a script tag. Here's a basic example to get started: Copy This is a good way to get started quickly without any build tools. Just keep in mind: **don’t store or expose real private keys or seeds in client-side code** in production apps. [PreviousIntroductionchevron-left](https://docs.keeta.com/) [NextCreate Your First Accountchevron-right](https://docs.keeta.com/introduction/create-your-first-account) Last updated 6 months ago * [Installation and Type Support](https://docs.keeta.com/introduction/start-developing#installation-and-type-support) * [Using the SDK in NodeJS](https://docs.keeta.com/introduction/start-developing#using-the-sdk-in-nodejs) * [Using the SDK in the Browser](https://docs.keeta.com/introduction/start-developing#using-the-sdk-in-the-browser) --- # Create Your First Account | Keeta Network To start interacting with KeetaNet, you’ll first need to create an account. Accounts are based on cryptographic key pairs, and they’re derived from a secure seed. This page shows you how to generate a seed, turn it into an account, and connect that account to the Keeta test network. circle-info Want to learn more about what an account is and how it works? Read: [What is an Account →](https://docs.keeta.com/components/accounts) [hashtag](https://docs.keeta.com/introduction/create-your-first-account#generate-a-seed) Generate a Seed ------------------------------------------------------------------------------------------------------------- The KeetaNet SDK includes utilities for generating secure random seeds. These seeds are used to create key pairs — think of them as the starting point for your identity on the network. circle-exclamation Your seed is sensitive information. Anyone with access to your seed can access your account. Here’s how to generate one and use it: Copy import * as KeetaNet from "@keetanetwork/keetanet-client"; async function main() { // Generate a secure random seed const seed = KeetaNet.lib.Account.generateRandomSeed({ asString: true }); console.log("Generated seed:", seed); // Create an account using the generated seed const account = KeetaNet.lib.Account.fromSeed(seed, 0); // Connect to the Keeta test network with this account const userClient = KeetaNet.UserClient.fromNetwork("test", account); console.log("Public key:", account.publicKeyString.toString()); } main().catch(console.error); #### [hashtag](https://docs.keeta.com/introduction/create-your-first-account#how-it-works) How it works * `generateRandomSeed()` creates a strong, random seed. * `fromSeed(seed, 0)` derives your first account (index `0`) from that seed. * `UserClient.fromNetwork("test", account)` connects you to the testnet using your new account. * You can use this client to send transactions, fetch chain data, or interact with the ledger. [hashtag](https://docs.keeta.com/introduction/create-your-first-account#receive-a-token) Receive a token ------------------------------------------------------------------------------------------------------------- If someone wants to send tokens to your Keeta account, they’ll need your **public address**. #### [hashtag](https://docs.keeta.com/introduction/create-your-first-account#option-1-public-address-from-a-newly-created-account) Option 1: Public Address from a Newly Created Account #### [hashtag](https://docs.keeta.com/introduction/create-your-first-account#option-2-public-address-from-an-existing-account) Option 2: Public Address from an Existing Account If you already have an account, you can share your `publicKey` to receive funds. This is the address others will send tokens to. [hashtag](https://docs.keeta.com/introduction/create-your-first-account#generate-a-qr-code) Generate a QR code ------------------------------------------------------------------------------------------------------------------- You can turn the public address into a QR code so others can scan and send easily. This works great on mobile wallets or in-person payments. To generate a QR code image: This gives you a **base64 image URL** (like `data:image/png;base64,...`) that you can embed in an `` tag: circle-check You don’t need a specific library — any QR code tool that supports text-to-QR conversion will work. Just pass in the address string, and you're good to go. Now you are ready to start sending your first transaction: [](https://docs.keeta.com/introduction/send-a-transaction) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FIJYk6VY0isQoWJwkEPHF%252Fsend.png%3Falt%3Dmedia%26token%3D1bcacda6-e3e7-4538-a878-6dd2005c3ae7&width=490&dpr=4&quality=100&sign=1c001479&sv=2) **Send a Transaction** Last updated 6 months ago * [Generate a Seed](https://docs.keeta.com/introduction/create-your-first-account#generate-a-seed) * [Receive a token](https://docs.keeta.com/introduction/create-your-first-account#receive-a-token) * [Generate a QR code](https://docs.keeta.com/introduction/create-your-first-account#generate-a-qr-code) Copy import * as KeetaNet from '@keetanetwork/keetanet-client'; // Generate a secure random seed const seed = KeetaNet.lib.Account.generateRandomSeed({ asString: true }); // Create a new account from the seed (index 0) const account = KeetaNet.lib.Account.fromSeed(seed, 0); // Get the public address const publicKey = account.publicKeyString.toString(); console.log("Your public Keeta address:", publicKey); Copy const existingSeed = "your existing seed string..."; const account = KeetaNet.lib.Account.fromSeed(existingSeed, 0); const publicKey = account.publicKeyString.toString(); Copy import { toDataURL } from "qrcode"; const qrCode = await toDataURL(accountPublicKey); Copy --- # Consensus | Keeta Network At its core, the Keeta Network utilizes a Delegated Proof of Stake (dPoS) voting protocol, which allows for quick consensus while ensuring decentralization. Keeta's block validation process follows a structured five-step sequence that ensures security and efficiency. The process begins when a client initiates a vote on a new block(s), sending their request to multiple network representatives. These representatives respond with temporary votes, providing initial validation of the proposed blocks. The client then requests verification of all temporary votes, creating a cross-validation layer. Following this, representatives submit their permanent votes, confirming their final decision on block validity. In the final step, the client broadcasts both the validated blocks and their associated votes to the network, where they are permanently added to the blockchain. ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2FpitcpcamWc0BKEe28I1D%2Fblobs%2FLwlGTA6iR7dBTOqeTn0v%2Fvote.jpg&width=768&dpr=4&quality=100&sign=bb8df594&sv=2) Each transaction must receive a sufficient number of votes before being broadcasted to the network. [PreviousData Structurechevron-left](https://docs.keeta.com/architecture/data-structure) [NextVoting Powerchevron-right](https://docs.keeta.com/architecture/consensus/voting-power) --- # Data Structure | Keeta Network Keeta's approach to blockchain technology centers around its use of a Directed Acyclic Graph (DAG) structure, representing a departure from traditional blockchain architectures. In this system, transactions are linked in a multi-dimensional web rather than a single, linear chain, allowing for parallel processing that increases the network's throughput and scalability. Unlike traditional blockchains, which struggle with scalability issues due to their linear nature and sequential transaction processing, Keeta's DAG system can handle a high volume of transactions simultaneously. This parallel processing eliminates the bottlenecks that plague traditional systems as network activity increases, enabling Keeta Network to scale efficiently as it grows. ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2FpitcpcamWc0BKEe28I1D%2Fblobs%2FbEKDqUSCQWXK8oUW3Yww%2Fdag.jpg&width=768&dpr=4&quality=100&sign=9e29a102&sv=2) Keeta Network processes transactions in parallel, improving performance. [PreviousSend a Transactionchevron-left](https://docs.keeta.com/introduction/send-a-transaction) [NextConsensuschevron-right](https://docs.keeta.com/architecture/consensus) --- # Create a Block | Keeta Network The block is digitally signed by the signer (if present, otherwise the account) and the signature is included in the block. The block is identified by its [hasharrow-up-right](https://static.test.keeta.com/docs/classes/KeetaNetSDK.Referenced.Block.html#hash-1) which is the hash of the block not including the signature. The KeetaNet SDK provides a block builder method which allows the user to create blocks in an incremental fashion. The block builder is created using the [BlockBuilderarrow-up-right](https://static.test.keeta.com/docs/classes/KeetaNetSDK.Referenced.BlockBuilder.html) class, however in most cases a [UserClientBuilderarrow-up-right](https://static.test.keeta.com/docs/classes/KeetaNetSDK.Referenced.UserClientBuilder.html) from a [UserClientarrow-up-right](https://static.test.keeta.com/docs/classes/KeetaNetSDK.UserClient.html#initbuilder) should be used because it will handle things like getting the correct network and previous block hash. [PreviousBlockschevron-left](https://docs.keeta.com/components/blocks) [NextOperationschevron-right](https://docs.keeta.com/components/blocks/operations) Last updated 6 months ago --- # Send a Transaction | Keeta Network Transactions are made up of one or more [operations](https://docs.keeta.com/components/blocks/operations) . Operations describe the specific actions your account wants to perform on the ledger — for example, sending tokens, setting permissions, or interacting with storage. Each operation is made up of **effects**, which are the actual changes applied to the [ledger](https://docs.keeta.com/components/ledger) . Take the `send` operation, for example: * It **decreases** the balance of the sender * It **increases** the balance of the recipient * It **validates** that the sender's balance doesn't drop below zero When you build a transaction, you're queuing up one or more of these operations to execute together. The KeetaNet SDK gives you tools to construct, compute, and publish these operations easily. circle-info You can think of a transaction as a container for operations, and operations as instructions to update the blockchain state. For a full list of available operations, check out the our [static documentation sectionarrow-up-right](https://static.test.keeta.com/docs/classes/KeetaNetSDK.Referenced.BlockOperation.html) . [hashtag](https://docs.keeta.com/introduction/send-a-transaction#code-example-sending-1-kta) Code Example: Sending 1 KTA ----------------------------------------------------------------------------------------------------------------------------- circle-info #### [hashtag](https://docs.keeta.com/introduction/send-a-transaction#when-running-this-code-make-sure-that-the-account-has-at-least-1-kta-in-the-account) When running this code, make sure that the account has at least 1 KTA in the account Copy /** * Load the KeetaNet Client SDK */ const KeetaNet = require('@keetanetwork/keetanet-client'); /** * This is the fake seed for the demo account, replace with a valid one */ const DEMO_ACCOUNT_SEED = 'D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0'; async function main() { // Create a signer account from the demo seed (account index 0) const signer_account = KeetaNet.lib.Account.fromSeed(DEMO_ACCOUNT_SEED, 0); console.log('🔑 Signer account:', signer_account.publicKeyString.get()); // Connect to the Keeta test network const client = KeetaNet.UserClient.fromNetwork('test', signer_account); // Start building a transaction const builder = client.initBuilder(); // Define the recipient (the faucet address for testing) const faucet_account = KeetaNet.lib.Account.fromPublicKeyString( 'keeta_aabszsbrqppriqddrkptq5awubshpq3cgsoi4rc624xm6phdt74vo5w7wipwtmi' ); // Add a send operation to the builder: 1 KTA to the faucet address builder.send(faucet_account, 1n, client.baseToken); // Compute the transaction blocks (Keeta breaks operations into blocks) const computed = await client.computeBuilderBlocks(builder); console.log('🧱 Computed blocks:', computed.blocks); // Publish the transaction to the network const transaction = await client.publishBuilder(builder); console.log('✅ Transaction published:', transaction); } main().then( () => process.exit(0), (err) => { console.error('❌ Error:', err); process.exit(1); } ); #### [hashtag](https://docs.keeta.com/introduction/send-a-transaction#whats-happening-here) What's Happening Here? * You **create a signer** using the account derived from your seed. * You connect to the **Keeta testnet** using `UserClient`. * You initialize a **transaction builder**, which lets you queue operations. * You queue a `send` operation with 1 KTA as the amount. * You compute the transaction blocks (how Keeta structures data before publishing). * You publish the transaction to the network. Last updated 6 months ago --- # Vote Stapling | Keeta Network A vote staple is the unit of distribution, creating a permanent voting context by combining multiple [blocks](https://docs.keeta.com/components/blocks) to all be voted on and published to the network at once. Nodes transmit vote staples over the network and clients publish vote staples. If one block in the staple is invalid, all blocks are rejected and must be sent back through the voting process without the invalid operation(s). Keeping the blocks and [votes](https://docs.keeta.com/architecture/consensus/votes) together increases efficiency and relieves the network from locating multiple pieces of data on the same operation. A staple is constructed from at least one block, and at least one vote. All votes within a single staple must be for the same blocks in the same order as the staple was constructed with. Additionally, a staple cannot contain mixed temporary and permanent votes. To maximize efficiency, the network uses compressed staples. The more similar the included blocks and votes contents are, the more the staple can be compressed. [PreviousVoteschevron-left](https://docs.keeta.com/architecture/consensus/votes) [NextLedgerchevron-right](https://docs.keeta.com/components/ledger) Last updated 5 months ago --- # Voting Power | Keeta Network Representatives' voting power in [dPoS](https://docs.keeta.com/architecture/consensus) is determined by the amount of Keeta tokens delegated to them. When token holders delegate their Keeta to a representative, they increase that representative's voting power in the consensus process. Representatives with more delegated tokens have stronger voting power when deciding whether to add new blocks to the chain. This system ensures that those trusted with more of the network's tokens have greater influence in validation decisions, while still allowing smaller token holders to participate in governance by choosing which representatives to support through delegation. The mechanism creates a balance between network security and decentralized participation. ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2FpitcpcamWc0BKEe28I1D%2Fblobs%2FUJiezMPMdosBln2nw4bm%2Fimage.png&width=768&dpr=4&quality=100&sign=b7fa6b18&sv=2) dPoS allows all participants to contribute to the voting process without requiring them to be representatives, and allows trustworthy parties to become representatives without personally holding substantial weight. [PreviousConsensuschevron-left](https://docs.keeta.com/architecture/consensus) [NextVoteschevron-right](https://docs.keeta.com/architecture/consensus/votes) --- # Votes | Keeta Network A vote is used by representatives as a means to communicate their intent to add a set of blocks to their ledger. Depending on the time-frame that an issued vote is valid for, it is either considered a temporary or permanent vote. Both temporary and permanent votes on Keeta Network are encoded as X.509 certificates. X.509 was chosen because it is a widely-used and well-known standard, and contains a flexible data structure using ASN.1. Each vote contains the following: **An Issuer:** The [account](https://docs.keeta.com/components/accounts) that signed the vote **Serial:** An arbitrary integer defined by the issuer which is generally incrementing. Two separate votes with the same issuer + serial will not be accepted by the network **Blocks:** A set of hashes of [blocks](https://docs.keeta.com/components/blocks) that the issuer is vouching validity for **Starting Time:** The timestamp when the vote was issued **Ending/Expiry Time:** The timestamp of when the vote expires and should not be considered in quorum anymore **Signature:** The issuers signature on the data included, proving that they were the one to issue the vote A vote is considered valid to a representative in the [voting process](https://docs.keeta.com/architecture/consensus) if it is not expired, the serial has not been seen before, and the set of blocks is valid. [PreviousVoting Powerchevron-left](https://docs.keeta.com/architecture/consensus/voting-power) [NextVote Staplingchevron-right](https://docs.keeta.com/architecture/consensus/vote-stapling) --- # Blocks | Keeta Network Blocks on Keeta Network are the fundamental mechanism by which the [ledger](https://docs.keeta.com/components/ledger) is updated. Each block contains an ordered set of operations which are performed by a given [account](https://docs.keeta.com/components/accounts) . Each block can hold multiple operations from the same account, and blocks can vary in size. Structure Blocks are encoded in ASN.1 DER, which enables them to be extensible in the future. The blocks’ size is dynamic, so it can be as large as the representatives will accept. [PreviousGet Ledger Historychevron-left](https://docs.keeta.com/components/ledger/get-ledger-history) [NextCreate a Blockchevron-right](https://docs.keeta.com/components/blocks/create-a-block) Last updated 7 months ago --- # Ledger | Keeta Network The ledger records everything on the network, including [user identities](https://docs.keeta.com/features/identity-profiles) , [account](https://docs.keeta.com/components/accounts) balances, operation history, and [votes](https://docs.keeta.com/architecture/consensus/votes) . All operations are added to the ledger once they are confirmed by the necessary representatives through the consensus mechanism and added to the account’s blockchain. The ledger contains the effects of every operation that has been made since the first operation on the network and can be referred to by the [nodes](https://docs.keeta.com/components/nodes) for record-keeping. The Keeta Network ledger maintains the state of the system and contains an up-to-date state for the following kinds of data: **Voting Power:** As a result of balances being delegated to a representative using the “Set Representative” operation, that representative gains [voting power](https://docs.keeta.com/architecture/consensus/voting-power) . Currently, voting power is the sum of all balances of the base token of the accounts which have delegated to that particular representative. **Balances:** Within the ledger, balances are maintained on a per-token basis on each account and are maintained as an arbitrary large big integer. **Tokens:** Tokens may be created with the “Create Identifier” operation and are stored within the Keeta Network ledger. Each token has the supply (total number of minted tokens) and outstanding balance of that token (tokens which have been issued to accounts) maintained as state within the ledger. **Certificates:** [Certificates](https://docs.keeta.com/components/certificates) are a specific type of metadata within the Keeta Network ledger which can be used to identify the user associated with an account. The certificate for an account is validated to share the same public key as the account. **Metadata:** As a result of the “Set Info” operation, some basic user information may be set on an address for informational purposes. **Permissions:** Keeta Network has an extensive [permissions](https://docs.keeta.com/components/accounts/permissions) system, allowing for fine-grained control over accounts, tokens, and the network. **Blocks:** In order to maintain ordering, [blocks](https://docs.keeta.com/components/blocks) are recorded in the ledger. Blocks contain all of the updates made to the ledger, as well as which accounts are being updated. **Votes:** Issued by ledgers as a side-effect of the ledger contents, votes are endorsements by a particular representative to insert a given block or set of blocks into their ledger. Votes come in two kinds: permanent and temporary. Only permanent votes end up on the“main” ledger, but a representative must maintain all votes it issues and so unpublished votes (whether permanent or temporary) will be stored in the “side ledger.” **Side Ledger:** The side ledger is a secondary area where unpublished votes are stored. All temporary votes will be unpublished, but the representative that issued them must keep track of them throughout the lifetime of the vote. [](https://docs.keeta.com/components/ledger/get-ledger-history) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FHgY49P2KrE8fvfMRmNHn%252Fdev.png%3Falt%3Dmedia%26token%3D3e7e484c-3852-4c22-a809-29bfcdebdd6f&width=752&dpr=4&quality=100&sign=9dab14c7&sv=2) **Get Ledger History** ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FHgY49P2KrE8fvfMRmNHn%252Fdev.png%3Falt%3Dmedia%26token%3D3e7e484c-3852-4c22-a809-29bfcdebdd6f&width=752&dpr=4&quality=100&sign=9dab14c7&sv=2) **Filter Ledger History** Last updated 7 months ago --- # Get Ledger History | Keeta Network The ledger history is the record of how the ledger state came to be. It is represented by the set of vote staples which have been applied to the ledger. This is expressed in two different ways in the KeetaNet SDK * The [UserClient.historyarrow-up-right](https://static.test.keeta.com/docs/classes/KeetaNetSDK.UserClient.html#history) method which returns a list of [vote staplesarrow-up-right](https://static.test.keeta.com/docs/classes/KeetaNetSDK.Referenced.VoteStaple.html) which have affected the given account. * The [UserClient.chainarrow-up-right](https://static.test.keeta.com/docs/classes/KeetaNetSDK.UserClient.html#chain) method which returns a list of [blocksarrow-up-right](https://static.test.keeta.com/docs/classes/KeetaNetSDK.Referenced.Block.html) which have been applied for a given account. These two differ in that the history method returns all vote staples which affected an account, even if they were not issued by the account -- for example if a transfer was made to the account, the history method would return the vote staple which included the transfer, but the chain method would not because it was not issued by the account. Additionally there is a method to [filter a list of vote staplesarrow-up-right](https://static.test.keeta.com/docs/classes/KeetaNetSDK.UserClient.html#filterstapleoperations-2) to a list of operations which are relevant to a specific account. This is useful because the list of operations in a vote staple may include changes that are uninteresting from an account perspective. [hashtag](https://docs.keeta.com/components/ledger/get-ledger-history#history-via-predefined-seed) History via predefined seed ----------------------------------------------------------------------------------------------------------------------------------- The script above demonstrates how to connect to the KeetaNet testnet and retrieve the account history using a predefined demo seed. Copy import * as KeetaNet from '@keetanetwork/keetanet-client'; import util from 'node:util'; // Demo seed — Replace with real seed const DEMO_SEED = 'D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0'; async function main() { // Create an account from the seed (index 0) const account = KeetaNet.lib.Account.fromSeed(DEMO_SEED, 0); // Connect to KeetaNet testnet using the account const client = KeetaNet.UserClient.fromNetwork('test', account); // Fetch the account history const history = await client.history(); // Print the account history in readable format console.log( '📜 Account history:', util.inspect(KeetaNet.lib.Utils.Helper.debugPrintableObject(history), { depth: 10, colors: true }) ); } main().catch((err) => { console.error('❌ Error:', err); process.exit(1); }); [hashtag](https://docs.keeta.com/components/ledger/get-ledger-history#history-of-a-public-account) History of a public account ----------------------------------------------------------------------------------------------------------------------------------- To retrieve the transaction history using a public Keeta address, you can use the provided script that demonstrates connecting to the KeetaNet testnet. By substituting a valid KeetaNet public key string, the script fetches the account's transaction history. [PreviousLedgerchevron-left](https://docs.keeta.com/components/ledger) [NextBlockschevron-right](https://docs.keeta.com/components/blocks) Last updated 4 months ago * [History via predefined seed](https://docs.keeta.com/components/ledger/get-ledger-history#history-via-predefined-seed) * [History of a public account](https://docs.keeta.com/components/ledger/get-ledger-history#history-of-a-public-account) Copy import * as KeetaNet from '@keetanetwork/keetanet-client'; import util from 'node:util'; async function main() { // Replace this with any valid KeetaNet public key string const publicKeyString = 'keeta_aabrrk5663nikbzhc3vr24nvwabyseqvlbf4ritnsoca2ujfurk6jqprplnm66y'; // Create an account object from the public key string const account = await KeetaNet.lib.Account.fromPublicKeyString(publicKeyString); // Connect to the KeetaNet testnet const client = KeetaNet.UserClient.fromNetwork('test', null, { account }); // Fetch the account's transaction history const history = await client.history(); // Display the history in a readable format console.log( '📜 Account history for', publicKeyString, util.inspect(KeetaNet.lib.Utils.Helper.debugPrintableObject(history), { depth: 10, colors: true }) ); } main().catch((err) => { console.error('❌ Error:', err); process.exit(1); }); --- # Ledger Pruning | Keeta Network Since some [nodes](https://docs.keeta.com/components/nodes) are intended to [vote](https://docs.keeta.com/architecture/consensus) on transactions, while others only view the transactions, the parts of the [ledger](https://docs.keeta.com/components/ledger) that are necessary to store can vary between nodes. To maximize efficiency within the network, ledger pruning allows the node host to store only the parts of the ledger that they determine are necessary to carry out their intended operations. In addition to increasing network efficiency, pruning saves nodes storage costs. There are four different types of nodes on Keeta Network, each with different pruning abilities. **Historical Node:** Historical nodes do not participate in ledger pruning and maintain the entire history of the ledger dating back to the network’s genesis. These nodes require the most storage since they maintain large amounts of data. They can be called upon for any historical information on any account, token, or transaction that has ever taken place on the network. **Current Node:** Current nodes only record and store the most recent blocks for each account. They maintain up-to-date information on the ledger’s most recent activity but not archive all historical data. Representatives must host at least a Current node but can host a Historical node if preferred. **Service Node:** Service nodes hold data for a subset of [accounts](https://docs.keeta.com/components/accounts) relevant to the node's host. These nodes also maintain updated representative network addresses, [voting power](https://docs.keeta.com/architecture/consensus/voting-power) , and public account identifiers, which reduces the client burden when interacting with the network. **Listen-only Node:** Listen-only nodes don’t record or store account activity—they listen in on network activity in real-time. They can take actions or measurements based on what is happening on the network at any given moment, but they don’t need to maintain storage for that activity since they are not recording any of it. [PreviousNodeschevron-left](https://docs.keeta.com/components/nodes) [NextAccountschevron-right](https://docs.keeta.com/components/accounts) --- # Nodes | Keeta Network A node is a piece of software that participates on Keeta Network. Nodes can be representatives that [vote](https://docs.keeta.com/architecture/consensus) on the network or participants that are only on the network to view the operations. Nodes that serve as representatives refer to their own copies of the [ledger](https://docs.keeta.com/components/ledger) to ensure that new operations are valid. Nodes are a key factor in assuring security and integrity within the network. Nodes on Keeta Network are hosted in cloud environments like as Google Cloud, allowing them to scale efficiently with the network. [PreviousupdatePermissionschevron-left](https://docs.keeta.com/components/blocks/operations/updatepermissions) [NextLedger Pruningchevron-right](https://docs.keeta.com/components/nodes/ledger-pruning) --- # Send | Keeta Network The **Send** operation is used to transfer tokens from one account to another on the Keeta Network. It’s the most basic transaction you can perform. Below is a minimal example that sends `1 KTA` to a target address using the KeetaNet SDK. Let’s walk through the minimal example for sending tokens using KeetaNet. 1 ### [hashtag](https://docs.keeta.com/components/blocks/operations/send#load-the-keeta-sdk-and-set-up-your-seed) Load the Keeta SDK and set up your seed You import the SDK and use a demo seed to generate an account. In real usage, you’d store this seed securely (never hardcoded). Copy const KeetaNet = require('@keetanetwork/keetanet-client'); const DEMO_ACCOUNT_SEED = 'D3M0D3M0...'; 2 ### [hashtag](https://docs.keeta.com/components/blocks/operations/send#create-your-signer-account) Create your signer account This generates an account object from the seed at index `0`. This account will be used to sign the transaction (i.e., it's the "sender"). Copy const sender = KeetaNet.lib.Account.fromSeed(DEMO_ACCOUNT_SEED, 0); 3 ### [hashtag](https://docs.keeta.com/components/blocks/operations/send#connect-to-the-keeta-test-network) Connect to the Keeta test network This initializes a client session connected to the **testnet**, using the sender account to authenticate. Copy const client = KeetaNet.UserClient.fromNetwork('test', sender); 4 ### [hashtag](https://docs.keeta.com/components/blocks/operations/send#define-the-recipient) Define the recipient You define who you're sending tokens to. In this example, it's a faucet address, but it could be any valid Keeta account. Copy const recipient = KeetaNet.lib.Account.fromPublicKeyString('keeta_...'); 5 ### [hashtag](https://docs.keeta.com/components/blocks/operations/send#initialize-a-transaction-builder) Initialize a transaction builder This creates a **builder**, which is used to queue one or more operations (like `send`, `setRep`, etc.) that will be packaged into a transaction. Copy const builder = client.initBuilder(); 6 ### [hashtag](https://docs.keeta.com/components/blocks/operations/send#add-the-send-operation) Add the send operation Copy builder.send(recipient, 1n, client.baseToken); This is the core of the operation. Let’s break it down: Argument Meaning `recipient` The recipient account object (created earlier) `1n` The amount to send, in tokens (as a `BigInt`). `1n` = 1 KTA `client.baseToken` The token to send (usually Keeta's native token, KTA) So this line is saying: > “Send 1 KTA to the specified recipient.” 7 ### [hashtag](https://docs.keeta.com/components/blocks/operations/send#optional-compute-the-blocks) (Optional) Compute the blocks This step lets you preview how the transaction will be constructed before sending it. It’s useful for debugging or simulation. Copy await client.computeBuilderBlocks(builder); 8 ### [hashtag](https://docs.keeta.com/components/blocks/operations/send#publish-the-transaction) Publish the transaction This sends your built transaction to the Keeta network, where it will be validated and added to the ledger. Copy await client.publishBuilder(builder); If all goes well, you’ve just sent 1 KTA to the recipient. You can now build on this with more operations, like minting, delegating, or managing tokens. [hashtag](https://docs.keeta.com/components/blocks/operations/send#complete-code-example) Complete Code Example -------------------------------------------------------------------------------------------------------------------- Copy const KeetaNet = require('@keetanetwork/keetanet-client'); // ⚠️ Demo seed, replace with working seed const DEMO_ACCOUNT_SEED = 'D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0D3M0'; async function main() { const sender = KeetaNet.lib.Account.fromSeed(DEMO_ACCOUNT_SEED, 0); const client = KeetaNet.UserClient.fromNetwork('test', sender); const recipient = KeetaNet.lib.Account.fromPublicKeyString( 'keeta_aabszsbrqppriqddrkptq5awubshpq3cgsoi4rc624xm6phdt74vo5w7wipwtmi' ); const builder = client.initBuilder(); builder.send(recipient, 1n, client.baseToken); // send 1 KTA await client.computeBuilderBlocks(builder); // optional but recommended await client.publishBuilder(builder); // send it to the network console.log('✅ Sent 1 KTA'); } main().catch(console.error); [PreviousOperationschevron-left](https://docs.keeta.com/components/blocks/operations) [NextReceivechevron-right](https://docs.keeta.com/components/blocks/operations/receive) Last updated 6 months ago * [Load the Keeta SDK and set up your seed](https://docs.keeta.com/components/blocks/operations/send#load-the-keeta-sdk-and-set-up-your-seed) * [Create your signer account](https://docs.keeta.com/components/blocks/operations/send#create-your-signer-account) * [Connect to the Keeta test network](https://docs.keeta.com/components/blocks/operations/send#connect-to-the-keeta-test-network) * [Define the recipient](https://docs.keeta.com/components/blocks/operations/send#define-the-recipient) * [Initialize a transaction builder](https://docs.keeta.com/components/blocks/operations/send#initialize-a-transaction-builder) * [Add the send operation](https://docs.keeta.com/components/blocks/operations/send#add-the-send-operation) * [(Optional) Compute the blocks](https://docs.keeta.com/components/blocks/operations/send#optional-compute-the-blocks) * [Publish the transaction](https://docs.keeta.com/components/blocks/operations/send#publish-the-transaction) * [Complete Code Example](https://docs.keeta.com/components/blocks/operations/send#complete-code-example) --- # Data Integrity | Keeta Network Ensuring data integrity is fundamental to the operation and trustworthiness of any blockchain system. In the context of Keeta Network, where transactions are validated through a meticulous two-phase voting process, the preservation of untampered data becomes even more vital. **Append-only Ledger:** Once a transaction has been validated and appended to the blockchain, it becomes an immutable record. This means that it cannot be altered or deleted without a consensus from a quorum of the network’s representatives. This feature ensures that historical data remains consistent. **Cryptographic Hashing:** Keeta Network employs SHA3-256 hashing for its records. This cryptographic hashing ensures that no alteration can take place within any record without affecting this record. **Chain Consistency:** Every block on Keeta Network's blockchain contains a reference to the previous block through its cryptographic hash. This chaining mechanism ensures that the blocks are in the correct sequence, and any attempt to modify a block would not only affect that block but also every subsequent block, making unauthorized changes easily detectable. **Use of TLS for Non-repudiation:** Keeta Network relies on Transport Layer Security (TLS) not just for encryption but importantly for non-repudiation. By utilizing HTTPS for all communication, it is possible to ensure that requests are being directed and delivered to the desired representatives. By implementing these mechanisms into its core, Keeta Network ensures the integrity of its data. This trustworthiness is foundational for the platform’s wide adoption and the overall security of the network. [PreviousPost Quantum Readinesschevron-left](https://docs.keeta.com/security/post-quantum-readiness) [NextProtection From Common Attackschevron-right](https://docs.keeta.com/security/protection-from-common-attacks) --- # Accounts | Keeta Network Accounts on Keeta Network refer to either the public key of a [key-pair](https://docs.keeta.com/components/key-pairs) or a deterministically generated account. Every account is given an address, which is a representation of their public key or some other uniquely identifiable information. Each account has a separate ordered blockchain within the [DAG](https://docs.keeta.com/architecture/data-structure) to store that account’s blocks. Keeta Network hosts a variety of account types. **Keyed Accounts:** Keyed accounts are comprised of a private and public key pair. They can digitally sign a block and are generally the only kind of accounts on other blockchains. On Keeta Network, these are the only accounts that can sign [votes](https://docs.keeta.com/architecture/consensus/votes) or [blocks](https://docs.keeta.com/components/blocks) . **Generated Accounts:** Generated accounts are special-purpose addresses generated deterministically from publicly available data. Unlike keyed accounts, they do not have the ability to sign transactions but serve other specific roles within the network. Generated accounts have an address which is deterministically derived from some fixed input, either from an operation within a block or well-known information such as the network ID. Ownership permissions will automatically be granted to the creator over the generated account. To publish a block to a generated account’s chain, a keyed account with proper permissions must sign a block for the generated account. **Network Accounts:** Each network has exactly one Network Account. This account is generated from the unique numeric representation of that network. Network accounts are used to assign network-wide permissions. For example, to create a new token on the network, the creator must have that permission assigned to them on the network account. The base token for the network is also generated from this address. **Storage Accounts:** Storage accounts are a versatile account type which can hold balances and are generally meant to be used as holding accounts for funds. They may be jointly owned or controlled by multiple accounts by setting the appropriate access control list (ACL) entries. **Token Accounts:** Tokens act as identifiers for different transferrable currencies on the network. Administrators and owners of these accounts have the ability to modify the total supply, modify an entity’s balance of the token, and grant/revoke a specific user’s ability to use the token. [PreviousLedger Pruningchevron-left](https://docs.keeta.com/components/nodes/ledger-pruning) [NextPermissionschevron-right](https://docs.keeta.com/components/accounts/permissions) --- # Storing Key Pairs | Keeta Network Keeta provides multiple options for key storage to cater to different security needs and use cases. For high-security applications, Hardware Security Modules (HSMs) can be used to store private keys, providing an additional layer of protection against unauthorized access. For more consumer-oriented applications, on-device storage solutions can be utilized. For example, a secure financial app on iOS could store private keys within the Secure Enclave on the user's device, giving them immediate access to their accounts and transactions. This approach ensures that sensitive data remains protected by hardware-level security, while still allowing for quick and convenient user interactions with their financial information. [PreviousKey Pairschevron-left](https://docs.keeta.com/components/key-pairs) [NextCertificateschevron-right](https://docs.keeta.com/components/certificates) --- # Post Quantum Readiness | Keeta Network Keeta Network is extensible to support additional cryptographic algorithms and can be migrated to fully support post-quantum cryptography (PQC), including deprecating all algorithms which are not post-quantum cryptography. [PreviousDigital Signatureschevron-left](https://docs.keeta.com/security/digital-signatures) [NextData Integritychevron-right](https://docs.keeta.com/security/data-integrity) --- # Native Tokenization | Keeta Network Tokenization is a cornerstone feature of Keeta Network, offering a flexible and efficient way to represent value. In the Keeta ecosystem, tokens are not smart contract-based assets but are rather native to the network itself. Tokens can be created for a wide range of applications, from representing digital currencies to creating digital versions of real-world assets. Unlike traditional blockchain platforms such as Ethereum, where tokens are typically created and managed through smart contracts, Keeta tokens exist as first-class citizens on the network. This fundamental difference in token architecture offers several advantages in terms of efficiency and flexibility. **Streamlined Operations and Cost Efficiency** The implementation of native tokenization eliminates the need for smart contract interactions for basic token operations. This design choice significantly reduces transaction complexity and associated costs. In contrast to Ethereum's tokenization model, where tokens are represented by smart contracts, Keeta's approach allows for more streamlined and cost-effective token operations. **Versatility and Ease of Use** Keeta's token system is designed for versatility and ease of use. Any approved network participant can create tokens, representing a wide range of assets. The system supports both fungible and non-fungible tokens, catering to diverse tokenization needs. Additionally, Keeta incorporates a dynamic rules engine that allows token creators to attach specific conditions or behaviors to their tokens, with these rules being automatically enforced by the network. [PreviousUtilizing Identity Profileschevron-left](https://docs.keeta.com/features/identity-profiles/utilizing-identity-profiles) [NextToken Creationchevron-right](https://docs.keeta.com/features/native-tokenization/token-creation) --- # Key Pairs | Keeta Network In the world of digital transactions, a key pair is like your personal lock and key set. It consists of a public key that can be freely shared, and a private key that is kept secret. On the Keeta Network, when a user makes a transaction, they use their private key to 'sign' it, creating a unique stamp. Anyone can then use your public key to verify that you indeed created the unique stamp, similar to how a bank verifies your signature on a check, but far more secure and impossible to forge. The Keeta network allows participants to manage their own key pairs, offering flexibility and security. The user has direct control over their transactions – no party can act on their behalf without their private key. Even if someone obtains your public key, they can't use it to make transactions or access your assets; only the private key can do that. This key pair system brings several advantages to Keeta. It ensures transactions are secure and tamper-proof, providing an accurate record of what party made each transaction – crucial for financial operations. Whether an individual makes a single payment or a crypto exchange manages millions, Keeta's key pair system provides the security and flexibility needed. ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2FpitcpcamWc0BKEe28I1D%2Fblobs%2FbCoX0l93RCiVFoSb2pQv%2Fimage.png&width=768&dpr=4&quality=100&sign=cf7ca5f0&sv=2) A public and private key are both needed to make transactions on the network. [PreviousSingle-Token Storage Accountchevron-left](https://docs.keeta.com/components/accounts/storage-accounts/single-token-storage-account) [NextStoring Key Pairschevron-right](https://docs.keeta.com/components/key-pairs/storing-key-pairs) --- # Protection From Common Attacks | Keeta Network Keeta has taken extensive measures to ensure that the network is built to be secure against common blockchain attacks. **Sybil attack** One of the predominant concerns in decentralized systems is the Sybil attack, where a single adversary controls multiple [nodes](https://docs.keeta.com/components/nodes) on the network, effectively trying to subvert the network’s functionality. Such an attack can disrupt honest nodes from achieving consensus or facilitate malicious activities. To counteract this, Keeta Network employs the use of X.509 certificates for certifying endpoints for representatives. This certification process ensures that each representative on the network is authenticated and can be trusted. X.509 certificates provide a standardized way of verifying the identity of participants and tying them to a public key infrastructure (PKI), making it computationally expensive and logistically challenging for an attacker to create a significant number of Sybil nodes. By relying on the trusted certification process, not only does Keeta Network dramatically reduce the potential for Sybil attacks, but it also establishes an added layer of trust among participants. This approach ensures that network nodes represent unique, authenticated entities, effectively fortifying the network’s resilience against such threats **51% attack** In blockchain system, a 51% attack refers to a situation where a single entity or coalition controls more than half of the computational power (for Proof of Work systems) or more than half of the authority (in Proof of Stake systems), enabling them to doublespend coins, prevent transaction confirmations, or halt the creation of new blocks. Such dominance poses a severe threat to the integrity and trustworthiness of the network. Keeta Network implements a proactive voting system to mitigate this threat. If a single representative amasses more than 50% of the voting weight, the Keeta Network protocol automatically adjusts the normal threshold for voting. This adaptive mechanism ensures that at least onetwo other representatives are required to reach a consensus, regardless of how much voting weight the dominant representative holds. This safeguard not only ensures that no single representative can unilaterally dictate the network’s decisions but also promotes a decentralized and democratic ethos within Keeta Network. Such a mechanism reinforces the network’s resilience against centralized threats, preserving the foundational principles of decentralization and security that Keeta Network upholds. **Spam attack** In the decentralized environment of blockchain systems, spam attacks often manifest as an influx of legitimate yet superfluous transactions. These transactions, while valid in their structure, are intentionally designed to flood the network, causing bottlenecks, delays, and inefficiencies. Keeta Network employs a strategic approach to counter such spamming tactics. Firstly, the network’s design incorporates a two-phase voting process, which acts as an initial filter to mitigate the volume of these transactions. However, in situations where an actor is persistent in dispatching a large number of genuine but unnecessary transactions, representatives on Keeta Network have the agency to respond. Representatives can observe transaction patterns and, upon identifying an attempt to spam the network, have the discretion to adjust transaction fees. By ratcheting up these fees in response to abnormal transactional activity, Keeta Network introduces a financial deterrent. This increased cost makes it prohibitively expensive for malicious entities to continue their spamming efforts. Furthermore, representatives can also choose to decline voting for these transactions entirely, effectively blocking them from being added to the blockchain. This dual-layered approach ensures that Keeta Network remains resilient against transactional spam, ensuring smooth operations and preserving network integrity. **Denial of service attack** A Denial of Service (DoS) attack aims to render a service unavailable by overwhelming it with traffic or exploiting specific vulnerabilities. In blockchain contexts, DoS attacks can severely hamper network operations, affecting all users connected to the network. Keeta Network’s design incorporates preemptive measures against DoS attacks. The aforementioned twophase voting process not only helps against spam attacks but is also effective in mitigating the impact of DoS attacks. By utilizing HTTPS in the voting process, Keeta Network can employ existing DDoS and DoS prevention mechanisms to safeguard the network. Additionally, representatives observing abnormal traffic or suspicious patterns indicative of a DoS attack can start imposing fees on suspected malicious actors. This proactive stance not only helps to minimize the impact of DoS attacks but also empowers the representatives to maintain the network’s integrity actively. [PreviousData Integritychevron-left](https://docs.keeta.com/security/data-integrity) [NextBenchmarks and Performance Metricschevron-right](https://docs.keeta.com/scalability/benchmarks-and-performance-metrics) --- # Separating Nodes from Hardware | Keeta Network Keeta's architecture separates [nodes](https://docs.keeta.com/components/nodes) from servers, allowing multiple servers to support a single node. This design enables both vertical and horizontal scaling without downtime, maintaining consistent transaction throughput under heavy loads and avoiding common network bottlenecks. Unlike traditional blockchain systems where nodes and servers are combined—requiring nodes to go offline for hardware upgrades—Keeta's approach permits hardware upgrades while keeping the network operational. This method delivers high performance without compromising decentralization or efficiency. By decoupling nodes from the underlying hardware, Keeta ensures that scaling and upgrades can be performed without disrupting network availability. This flexible architecture sets Keeta apart from competitors, providing continuous operation at full capacity during expansion or maintenance activities. ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2FpitcpcamWc0BKEe28I1D%2Fblobs%2FsQFTT71J1iN1x2XZZMR3%2Fservers.jpg&width=768&dpr=4&quality=100&sign=28ec4bf7&sv=2) By separating nodes from servers, Keeta Network delivers high performance without compromising decentralization or efficiency. [PreviousBenchmarks and Performance Metricschevron-left](https://docs.keeta.com/scalability/benchmarks-and-performance-metrics) [NextEliminating Mempoolschevron-right](https://docs.keeta.com/scalability/eliminating-mempools) Last updated 4 months ago --- # Digital Signatures | Keeta Network Keeta Network uses digital signatures for digitally signing [blocks](https://docs.keeta.com/components/blocks) and [votes](https://docs.keeta.com/architecture/consensus/votes) , and cryptographic hashing for referencing blocks. The network currently supports 3 different cryptographic algorithms for performing digital signatures, but is extensible to support additional algorithms, as well as deprecating algorithms in the future should the need arise. The currently supported algorithms are: * EcDSA with secp256k1 * EcDSA with secp256r1 * Ed25519 [PreviousGet Certificateschevron-left](https://docs.keeta.com/components/certificates/get-certificates) [NextPost Quantum Readinesschevron-right](https://docs.keeta.com/security/post-quantum-readiness) --- # Storage Accounts | Keeta Network Storage accounts represent a versatile account type designed to hold balances and serve as custodial accounts for funds. These accounts can be shared among multiple users or entities and can undergo complete ownership changes. The defining feature of storage accounts is their ability to implement custom rules regarding the types of tokens they can receive and who is permitted to deposit into them. This is achieved through Keeta’s permission system, allowing for fine-grained control over account operations. Storage accounts are particularly useful for scenarios requiring joint fund management, escrow services, or segregated fund storage with specific access controls. ### [hashtag](https://docs.keeta.com/components/accounts/storage-accounts#core-features) Core Features * **Advanced permissions:** Set fine-grained rules for who can view, deposit, or withdraw funds. * **Multi-entity ownership:** Accounts can be shared across people, organizations, or automated systems. * **Custom account logic:** Enable workflows such as joint approvals, time locks, escrow, or spending limits. * **Flexible transferability:** Easily change or assign ownership when needed. ### [hashtag](https://docs.keeta.com/components/accounts/storage-accounts#how-users-can-leverage-storage-accounts) How Users Can Leverage Storage Account The Keeta Network introduces an innovative approach to digital banking by allowing users to utilize a single key pair to open and manage multiple accounts across different banks. This process begins with the user generating a key pair via the Keeta Network, consisting of both a public and private key. The public key serves as a secure identifier that can be shared with various financial institutions. When a user wishes to open an account with a bank, they simply share their public key. The bank then uses this public key to generate and open a storage account on the Keeta Network specifically for that user. This process can be repeated with multiple banks, all using the same public key. As a result, users can establish and access numerous accounts across various financial institutions without the need to generate and manage multiple sets of cryptographic keys. This system offers significant advantages in terms of user convenience and security. It simplifies account management for individuals who maintain relationships with multiple banks or financial institutions, while still preserving the high level of security associated with cryptographic key pairs. ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252F2wL1DkMqa3kSW4EOs2cV%252Fimage.png%3Falt%3Dmedia%26token%3D127cc5d8-735d-4bd0-8f91-b1c9c6af30a7&width=768&dpr=4&quality=100&sign=4513c2df&sv=2) Flow of Creating a Joint Accounts on the Network [PreviousPermissionschevron-left](https://docs.keeta.com/components/accounts/permissions) [NextCreate a Storage Accountchevron-right](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account) Last updated 6 months ago * [Core Features](https://docs.keeta.com/components/accounts/storage-accounts#core-features) * [How Users Can Leverage Storage Account](https://docs.keeta.com/components/accounts/storage-accounts#how-users-can-leverage-storage-accounts) --- # Benchmarks and Performance Metrics | Keeta Network TPS Throughput Testing Results Cloud Provider Ledger Database Max TPS AWS DynamoDB 2M AWS DynamoDB 3.5M GCP Spanner 13M GCP Spanner 11.2M Future Testing Configurations Representatives Other Nodes Transactions per Block Blocks per Staple 5 0 1000 1 5 10 1 to 10 1 to 2 5 30 1 1 [PreviousProtection From Common Attackschevron-left](https://docs.keeta.com/security/protection-from-common-attacks) [NextSeparating Nodes from Hardwarechevron-right](https://docs.keeta.com/scalability/separating-nodes-from-hardware) Last updated 6 months ago --- # Certificates | Keeta Network Certificates on the network can be attached to [accounts](https://docs.keeta.com/components/accounts) to serve as digital credentials that validate the identity, qualifications, and capabilities of participants within the system. These certificates are fundamental to establishing trust and enabling secure interactions between various parties on the network. ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2FpitcpcamWc0BKEe28I1D%2Fblobs%2Fbdmu22ArT8dtZspRPZkD%2Fimage.png&width=768&dpr=4&quality=100&sign=1a820e1c&sv=2) ### [hashtag](https://docs.keeta.com/components/certificates#scope-and-flexibility) Scope & Flexibility At their core, Keeta certificates are structured pieces of information that can represent a wide range of attributes. These may include Know Your Customer (KYC) verifications, business licenses, regulatory compliance certifications, and other important qualifications. The flexibility of the certificate system allows for the representation of virtually any relevant attribute that may be required for network operations. ### [hashtag](https://docs.keeta.com/components/certificates#dynamic-nature) Dynamic Nature One of the key features of certificates on the Keeta Network is their dynamic nature. Unlike traditional static credentials, these certificates can be updated and modified over time through [Keeta's Dynamic Rule Engine](https://docs.keeta.com/features/native-tokenization/built-in-rules-engine) . This adaptability ensures that the information remains current and relevant, reflecting any changes in a participant's status or qualifications. ### [hashtag](https://docs.keeta.com/components/certificates#compliance-and-security) Compliance & Security Certificates play a crucial role in the network's compliance and security framework. They not only validate the legitimacy of participants but also define their capabilities within the system. For example, a certificate might specify transaction limits, access rights, or the types of operations a participant is authorized to perform. This certificate-based approach to identity and permissions management helps streamline processes, and reduce verification overhead. [PreviousStoring Key Pairschevron-left](https://docs.keeta.com/components/key-pairs/storing-key-pairs) [NextGet Certificateschevron-right](https://docs.keeta.com/components/certificates/get-certificates) * [Scope & Flexibility](https://docs.keeta.com/components/certificates#scope-and-flexibility) * [Dynamic Nature](https://docs.keeta.com/components/certificates#dynamic-nature) * [Compliance & Security](https://docs.keeta.com/components/certificates#compliance-and-security) --- # Get Certificates | Keeta Network A certificate is a mechanism for one entity (the issuer) to assert specific attributes about another entity (the subject). Each certificate contains: * **Subject's Public Key** — The Keeta account identifier * **Certified Attributes** — Identity data like full name, email, or address * **Issuer's Digital Signature** — Cryptographic proof of authenticity Keeta extends X.509 certificates to support both public and sensitive attributes. Sensitive attributes use encryption and cryptographic commitments to enable selective disclosure — subjects can prove specific values to third parties without exposing data to others ### [hashtag](https://docs.keeta.com/components/certificates/get-certificates#getting-certificates) Get Certificates via the SDK To fetch certificates tied to any Keeta account address (read-only), create a client with a `null` signer and pass the target `account` in the options: Copy import * as KeetaNet from '@keetanetwork/keetanet-client'; async function main() { // Target address const publicKeyString = 'keeta_aabg2lkwuy4gvzr44cniihdmwzinfuunqv4qgsuhbq7jpt4qms622tldjbdexwy'; const account = await KeetaNet.lib.Account.fromPublicKeyString(publicKeyString); // Read-only client bound to target account const client = KeetaNet.UserClient.fromNetwork( 'test', null, { account } ); try { // Fetch and sort certificates by issuance date (newest first) const response = await client.getCertificates(); const sorted = response.sort( (a, b) => b.certificate.notBefore.valueOf() - a.certificate.notBefore.valueOf() ); console.log(`Found ${sorted.length} certificates for ${account}`); // Display basic info for each certificate sorted.forEach(({ certificate }) => { console.log('Issuer:', certificate.issuerDN); console.log('Subject:', certificate.subjectDN); console.log('Valid until:', certificate.notAfter.toISOString()); console.log('—'); }); } finally { await client.destroy(); } } main().catch(console.error); [PreviousCertificateschevron-left](https://docs.keeta.com/components/certificates) [NextDigital Signatureschevron-right](https://docs.keeta.com/security/digital-signatures) Last updated 4 months ago --- # Identity Profiles | Keeta Network All of the [certificates](https://docs.keeta.com/components/certificates) issued by Certificate Authorities (CAs) are brought together to collectively form a comprehensive digital profile for each user on the Keeta network. A user might have their identity verified by a government agency, their financial credentials certified by a bank, their professional qualifications validated by an industry expert, and their educational background confirmed by a university. This creates a rich, multi-faceted overview of the user's verified attributes, all linked to their unique public key on the network. Such a system allows for efficient and secure sharing of verified information across different services and applications within the Keeta ecosystem, reducing repetitive verification processes and enhancing user privacy by allowing selective disclosure of relevant certificates as needed for specific interactions or transactions. ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2FpitcpcamWc0BKEe28I1D%2Fblobs%2F9Ao5R0sKtRx61F3XrHdS%2FFrame%25201538231347.png&width=768&dpr=4&quality=100&sign=5fe7bd3a&sv=2) User can utilize certificates from a variety of CAs to create a compehensive digital profile. [PreviousEliminating Mempoolschevron-left](https://docs.keeta.com/scalability/eliminating-mempools) [NextUtilizing Identity Profileschevron-right](https://docs.keeta.com/features/identity-profiles/utilizing-identity-profiles) --- # Creating an Anchor | Keeta Network Any participant on Keeta Network can create an anchor to any external system. The anchor hosts can set the rules for their own anchor and charge fees as desired. To allow for a competitive marketplace, there is no limit to how many participants can host the same anchor. For example, if five different banks host an anchor to the same domestic payment rail, network users can determine which bank's anchor they would like to utilize, based on the fees, rules, and performance of the anchor. The same dynamic is true with connected blockchain networks and their native digital assets. Some anchors may choose to join the network as a public anchor, hoping to attract as many users as possible. Other anchors may choose to join the network as a private anchor for a specific group. Using the banks as an example again, one bank may host the domestic payment rail to any local citizen while another bank hosts the same domestic payment rail specifically for users that are certified members of their bank. [PreviousAnchorschevron-left](https://docs.keeta.com/features/anchors) [NextPublic Networkchevron-right](https://docs.keeta.com/applications/public-network) Last updated 6 months ago --- # Permissions | Keeta Network Two types of permissions are used in Keeta Network: “base permissions” and “external permissions.” Base permissions are represented by a symbolic name that corresponds to a specific value. External permissions are not managed by Keeta Network and can hold arbitrary flags (offsets) managed by an external party. **Encoding:** Both base and external permissions are encoded using a bit-field of offsets to leverage bitwise operations for combining and checking permissions in a compact, fast bit-based expression. Subsequent modifications are likewise very efficient. Within the network, bit-fields will always be represented as one of the following: * An array of numbers representing the index of true offsets within the bit-field * The integer output of the bitwise operations * For the case of base flags, an array of the flag names **Access Control List:** On Keeta Network, permissions are stored and represented alongside information that describes their use. An access control list (ACL) entry will contain the following fields: * Principal: The address identifying the actor on the network accessing an entity * Entity: The network address that is being acted upon by the principal, and the address whose chain in which the ACL modifications occur * Target: An optional address narrowing the scope of a permission * Permissions: The list of base and/or external permissions granted, both represented as bitfields. **Permission Hierarchy:** Permissions on Keeta Network are always read from most to least specific, with the default if none are set being empty. They will always be read with this priority. Permissions do not inherit from level to level. If one is defined it will override the less specific entry. 1. ACL entry that matches the principal + entity + target exactly 2. ACL entry that matches the principal + entity exactly, but does not include a specific target 3. (If the entity is able to) The default permission set by the entity 4. If none of the above are found, the permissions are assumed to be empty. For example, if a storage address grants the ability for one user “SEND ON BEHALF” with no target, that user will be able to send any token from the storage [account](https://docs.keeta.com/components/accounts) . If the storage account then creates an ACL entry for the same user with a specific token as a target not including “SEND ON BEHALF" that user will still be able to send any token, just excluding the specific token in which permissions were removed from. **Base Permissions:** Base permissions each have a symbolic name and use case defined by Keeta Network. Each symbolic name is tied to a specific offset to be used in the bit-field, and a specific use on the network. **External Permissions:** External permissions are not managed by Keeta Network. They can hold arbitrary flags managed by an external party. External parties can set these to arbitrary values using the same bitfield format as their counterpart. Within the network each offset is not tied to a symbolic name, and such are always only represented as a bitfield. If an external party wants to represent these using symbolic names, there is a client-side method to do so. **Ownership:** The “OWNER” base permission represents ownership of an address. This is only applicable to generated account identifiers, as the owner of other accounts is the holder of the private key. On identifier creation, the creator is automatically given this permission. After that point, there must always be exactly one address with the “OWNER” flag, if any modifications are made, they must be done within the same vote staple as to not have the end count not equal to one. Some examples where an account created a storage account and is trying to transfer ownership include: * Invalid Ownership Modification * The owner of a storage account signs a block granting a different address the OWNER permission, leaving two owners * The owner of a storage account signs a block lowering their own permissions to ADMIN, leaving no owners * The owner of a storage account performs both the correct addition and removal, but performs the action in two vote staples, making each one invalid alone. * Valid Ownership Modification * The owner of a storage account signs a block in which the new owner is granted the OWNER permission and the previous owner is re-assigned a bitfield not including OWNER. **Delegation:** On Keeta Network, the “PERMISSION DELEGATE ADD” and “PERMISSION DELEGATE REMOVE” flags both represent the ability for the principal to re-assign permissions to other addresses for the entity that these were granted from. Both of these flags work in a similar way, but each representing a different method (“AdjustMethod”) that is being used in the “MODIFY PERMISSIONS” block operation. A principal with either of these flags is only able to add or remove a subset of the permissions that they have on the same entity, and is not able to re-grant either of the delegation flags unless they are an admin of the entity. [PreviousAccountschevron-left](https://docs.keeta.com/components/accounts) [NextStorage Accountschevron-right](https://docs.keeta.com/components/accounts/storage-accounts) Last updated 5 months ago --- # Eliminating Mempools | Keeta Network A key feature of Keeta Network is the elimination of memory pools, or "mempools." In traditional blockchain networks, mempools serve as waiting areas for transactions before they're added to a block. This can lead to delays and increased transaction fees during periods of high network activity. Keeta's architecture bypasses this issue entirely. By leveraging the [DAG structure](https://docs.keeta.com/architecture/data-structure) and advanced [consensus mechanism](https://docs.keeta.com/architecture/consensus) , transactions can be quickly validated and incorporated into the network without the need for a mempool intermediary. The result is fast transaction processing and significantly reduced fees. ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2FpitcpcamWc0BKEe28I1D%2Fblobs%2FPi7P8P1KKkdfAvAzXJg9%2Fimage.png&width=768&dpr=4&quality=100&sign=88201f8d&sv=2) Traditional blockchains utilize mempools as waiting areas for transactions. [PreviousSeparating Nodes from Hardwarechevron-left](https://docs.keeta.com/scalability/separating-nodes-from-hardware) [NextIdentity Profileschevron-right](https://docs.keeta.com/features/identity-profiles) --- # Anchors | Keeta Network Keeta Network's anchor feature allows users to securely move their digital assets across multiple blockchain networks without intermediaries or extensive fees. Any blockchain network can be connected to Keeta Network through the Anchor feature, allowing that blockchain's native assets to be traded freely with any other asset on Keeta Network. This feature brings a new level of interoperability to the blockchain ecosystem that is otherwise fragmented. Any foreign asset that is tokenized on Keeta Network is done so 1:1 and can be returned back to the native blockchain at any point. Upon sending the asset back to its native blockchain, the original asset is released and the tokenized version on Keeta Network is burned. Traditional payment systems like the Society for Worldwide Interbank Financial Telecommunications (SWIFT) and the Automated Clearing House (ACH) can also be connected to Keeta Network, creating a payment ecosystem with unprecedented global interoperability. Fiat currencies can be transferred with the same security and performance as digital assets, and the two can be interchanged seamlessly. Regulatory compliance protocols are built-in to the network natively, making the ecosystem feasible for central banks, commercial banks, and other highly-regulated financial entities. [PreviousBuilt-in Rules Enginechevron-left](https://docs.keeta.com/features/native-tokenization/built-in-rules-engine) [NextCreating an Anchorchevron-right](https://docs.keeta.com/features/anchors/creating-an-anchor) --- # Operations | Keeta Network [Operationsarrow-up-right](https://static.test.keeta.com/docs/classes/KeetaNetSDK.Referenced.BlockOperation.html) describe the actions performed by an account on the ledger. They are fundamentally composed of effects, which are the specific changes or constraints performed on the ledger. An example operation is a [Sendarrow-up-right](https://static.test.keeta.com/docs/classes/KeetaNetSDK.Referenced.BlockOperationSEND.html) operation which has the effects of decrementing the balance of the sender, incrementing the balance of the receiver, and validating that the sender's balance does not drop below zero. The KeetaNet SDK provides [a number of operationsarrow-up-right](https://static.test.keeta.com/docs/classes/KeetaNetSDK.Referenced.BlockOperation.html) which are used to perform actions on the ledger. [](https://docs.keeta.com/components/blocks/operations/send) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FIJYk6VY0isQoWJwkEPHF%252Fsend.png%3Falt%3Dmedia%26token%3D1bcacda6-e3e7-4538-a878-6dd2005c3ae7&width=490&dpr=4&quality=100&sign=1c001479&sv=2) **Send** [](https://docs.keeta.com/components/blocks/operations/receive) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252F8mm7r1fUZEA8Sm4MOOw7%252Freceive.png%3Falt%3Dmedia%26token%3D109aaac5-1556-4e55-b651-ee16ac0ab5ba&width=490&dpr=4&quality=100&sign=c8ab18&sv=2) **Receive** [](https://docs.keeta.com/components/blocks/operations/setinfo) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FmIkG8ahOy0sBY3wLEm75%252Fset_info.png%3Falt%3Dmedia%26token%3D1a16da49-9bae-400c-a778-3307fbdddb1f&width=490&dpr=4&quality=100&sign=fc4ba30&sv=2) **setInfo** [](https://docs.keeta.com/components/blocks/operations/modifytokensupply) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FYP2AiVzFl0aAbaaSc1Lm%252Ftoken_balance.png%3Falt%3Dmedia%26token%3Da6a10534-5f11-43d8-bb3a-40a8a1a908a5&width=490&dpr=4&quality=100&sign=892b3543&sv=2) **modifyTokenBalance** [](https://docs.keeta.com/components/blocks/operations/modifytokenbalance) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252Fm3XFV7gHcVZrDx68kjIs%252Fsupply.png%3Falt%3Dmedia%26token%3Dd4663818-1048-4098-9061-6e0093381b4d&width=490&dpr=4&quality=100&sign=683c2b84&sv=2) **modifyTokenSupply** [](https://docs.keeta.com/components/blocks/operations/generateidentifier) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FjtIRbQbCvbmKeKvijR6R%252Fcreate_id.png%3Falt%3Dmedia%26token%3Ddad5c311-799f-4158-8b4b-9a5a4ba3f9fc&width=490&dpr=4&quality=100&sign=1fae9c79&sv=2) **generateIdentifier** [](https://docs.keeta.com/components/blocks/operations/updatepermissions) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FuyI45RtkfIkId71dXd6l%252Fmodify_perm.png%3Falt%3Dmedia%26token%3Dd666c17a-196f-4e45-8e66-12a66d068dd9&width=490&dpr=4&quality=100&sign=93a408a3&sv=2) **updatePermissions** [PreviousCreate a Blockchevron-left](https://docs.keeta.com/components/blocks/create-a-block) [NextSendchevron-right](https://docs.keeta.com/components/blocks/operations/send) Last updated 6 months ago --- # Set Permissions | Keeta Network circle-info Documentation is coming soon. The [SDKarrow-up-right](https://static.test.keeta.com/docs/classes/KeetaNetSDK.Referenced.Permissions.html) is live and can be used today. [PreviousBurn Tokenschevron-left](https://docs.keeta.com/features/native-tokenization/token-creation/burn-tokens) [NextBuilt-in Rules Enginechevron-right](https://docs.keeta.com/features/native-tokenization/built-in-rules-engine) Last updated 5 months ago --- # setInfo | Keeta Network The `setInfo()` operation allows you to attach **custom metadata** and define **default permissions** for an account, such as a token, identifier, or other asset. It's most commonly used to describe assets (e.g., NFTs or tokens) or set defaults for how other users can interact with them. This operation is part of the `builder` and is added to a transaction before publishing. [hashtag](https://docs.keeta.com/components/blocks/operations/setinfo#when-to-use) When to Use --------------------------------------------------------------------------------------------------- * Naming a token or identifier * Describing its purpose or contents * Embedded metadata, could be optionally signed to prove authenticity * Defining default access permissions Here's a simplified example used within a transaction builder. You can find a full implementation in the '[Tokenizing Real-World Assets](https://docs.keeta.com/guides/tokenizing-real-world-assets) ' section of the guide. Copy builder.setInfo({ name: 'DEMORWA', description: 'Demo Token for Real World Asset', metadata: metadata_base64, // base64-encoded JSON with asset info + signature defaultPermission: new KeetaNet.lib.Permissions(['ACCESS'], []) }, { account: token.account // the account you're attaching this info to }); #### [hashtag](https://docs.keeta.com/components/blocks/operations/setinfo#explanation-of-each-field) Explanation of Each Field * `**name**` – A human-readable name for the asset/account (e.g. token symbol). * `**description**` – A short description or summary of the asset. * `**metadata**` – A base64-encoded string containing structured data. This can include things like signed JSON that links the on-chain token to a real-world asset. The data can also optionally be encrypted. * `**defaultPermission**` – A permissions object that controls what other accounts are allowed to do with this entity. E.g. ACCESS permission gives anyone the ability to hold and transfer the asset to others. [hashtag](https://docs.keeta.com/components/blocks/operations/setinfo#why-use-it) Why Use It? -------------------------------------------------------------------------------------------------- `setInfo()` is especially useful for: * Setting up NFTs or tokens that represent real-world assets * Making assets easily discoverable or identifiable * Defining behavior for asset holders without custom logic circle-exclamation Keep in mind that metadata is public and immutable once published as part of a transaction. Last updated 6 months ago * [When to Use](https://docs.keeta.com/components/blocks/operations/setinfo#when-to-use) * [Why Use It?](https://docs.keeta.com/components/blocks/operations/setinfo#why-use-it) --- # Built-in Rules Engine | Keeta Network Keeta's blockchain includes a rules engine that allows token creators to attach specific rules to tokens when they are issued, or later in their life-cycle. These rules define how the token can be used, transferred, or managed on the network. For example, a rule might restrict transfers to certain users, set specific transaction dates, or require approval before transactions can occur. ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2FpitcpcamWc0BKEe28I1D%2Fblobs%2FGZtoXbDYoUS0L7jcM1sL%2Fcalendar.jpg&width=768&dpr=4&quality=100&sign=d22057c9&sv=2) Time-Locked Tokens Example ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2FpitcpcamWc0BKEe28I1D%2Fblobs%2FmfVL7CvADHbYOFhQdI76%2Fadminrule.jpg&width=768&dpr=4&quality=100&sign=bbb59b8&sv=2) Transaction Approval Requirements Example **Automatic Enforcement of Token Rules** The network automatically enforces these attached rules. Whenever a transaction involving the token is initiated, the network checks the token's rules to ensure the transaction complies with them. If the transaction doesn't meet the specified conditions, the network will deny it. This automatic enforcement ensures that all token activities adhere to the intended guidelines without the need for manual oversight. **Updating Token Rules After Issuance** One of the key features of Keeta's rules engine is the ability to update the rules even after the token has been created and distributed. Token issuers can modify the rules to adapt to new regulations, changing business needs, or other factors. Once the rules are updated, the network applies the new conditions to all future transactions involving that token. [PreviousSet Permissionschevron-left](https://docs.keeta.com/features/native-tokenization/token-creation/set-permissions) [NextAnchorschevron-right](https://docs.keeta.com/features/anchors) --- # updatePermissions | Keeta Network The ‎`updatePermissions()` operation lets you change what an account or identifier is allowed to do on the Keeta Network. Use it to grant, restrict, or remove access to specific token-related actions for a given account. Copy userClient.updatePermissions( targetAccount, new Client.lib.Permissions([\ "ACCESS",\ "ADMIN",\ // ...add or remove permissions as needed\ ]), tokenAccount, Client.lib.Block.AdjustMethod.SET, // Optional: SET (default), ADD, or SUBTRACT { account: tokenAccount } // Optional: options ) _targetAccount_: The account to update permissions for. _permissions_: The new permissions to assign, as a ‎\`Permissions\` object. _tokenAccount_: The token (public address) these permissions relate to. _method_ (optional): How to update permissions (‎\`SET\`, ‎\`ADD\`, or ‎\`SUBTRACT\`). _options_ (optional): Additional settings (e.g. which account is performing the update). [hashtag](https://docs.keeta.com/components/blocks/operations/updatepermissions#when-to-use) When to Use ------------------------------------------------------------------------------------------------------------- * Grant new permissions to an account for a specific token. * Remove or revoke existing permissions from an account. * Change roles or access after onboarding, role changes, or security reviews. * Respond to organizational changes or update access control policies. * Maintain secure and flexible token operations on the network. [hashtag](https://docs.keeta.com/components/blocks/operations/updatepermissions#permission-types) Permission Types ----------------------------------------------------------------------------------------------------------------------- Specify any combination of permission strings as defined in the SDK. For the complete list and descriptions, refer to the [static documentationarrow-up-right](https://static.test.keeta.com/docs/enums/KeetaNetSDK.Referenced.BaseFlag.html#permission_delegate_add) . [hashtag](https://docs.keeta.com/components/blocks/operations/updatepermissions#requirements) Requirements --------------------------------------------------------------------------------------------------------------- To update permissions, the calling account must have the ‎`ACCESS` right on the token. Additionally, the account must either be an ‎`ADMIN` or have the ‎`PERMISSION_DELEGATE_ADD` permission. [hashtag](https://docs.keeta.com/components/blocks/operations/updatepermissions#code-example-how-to-remove-access-permission-from-an-account) Code Example: How to Remove ACCESS Permission from an Account ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 ### [hashtag](https://docs.keeta.com/components/blocks/operations/updatepermissions#identify-the-target-account-and-token) Identify the Target Account and Token Decide which account should lose access (‎`accountToDenyAccess`) and the token (‎`tokenAccount`) this affects. 2 ### [hashtag](https://docs.keeta.com/components/blocks/operations/updatepermissions#prepare-the-permissions-object) Prepare the Permissions Object Create a ‎`Permissions` object with the permission you want to remove. 3 ### [hashtag](https://docs.keeta.com/components/blocks/operations/updatepermissions#call-updatepermissions-with-the-substract-method) Call updatePermissions with the SUBSTRACT method Use the ‎`SUBTRACT` method to remove the permission. circle-info If you wanted to add a permission instead, use the ‎`Client.lib.Block.AdjustMethod.ADD` and to set it `Client.lib.Block.AdjustMethod.SET`. 4 ### [hashtag](https://docs.keeta.com/components/blocks/operations/updatepermissions#confirm-the-update) Confirm the Update Wait for confirmation on the network to ensure the permission has been removed. circle-exclamation The account performing this operation must have ‎`ACCESS` and either ‎`ADMIN` or ‎`PERMISSION_DELEGATE_ADD` rights on the token. [PreviousmodifyTokenBalancechevron-left](https://docs.keeta.com/components/blocks/operations/modifytokenbalance) [NextNodeschevron-right](https://docs.keeta.com/components/nodes) Last updated 6 months ago * [When to Use](https://docs.keeta.com/components/blocks/operations/updatepermissions#when-to-use) * [Permission Types](https://docs.keeta.com/components/blocks/operations/updatepermissions#permission-types) * [Requirements](https://docs.keeta.com/components/blocks/operations/updatepermissions#requirements) * [Code Example: How to Remove ACCESS Permission from an Account](https://docs.keeta.com/components/blocks/operations/updatepermissions#code-example-how-to-remove-access-permission-from-an-account) * [Identify the Target Account and Token](https://docs.keeta.com/components/blocks/operations/updatepermissions#identify-the-target-account-and-token) * [Prepare the Permissions Object](https://docs.keeta.com/components/blocks/operations/updatepermissions#prepare-the-permissions-object) * [Call updatePermissions with the SUBSTRACT method](https://docs.keeta.com/components/blocks/operations/updatepermissions#call-updatepermissions-with-the-substract-method) * [Confirm the Update](https://docs.keeta.com/components/blocks/operations/updatepermissions#confirm-the-update) Copy // Example dummy public keys (replace with real ones in production) const accountToDenyAccess = "kta_1dummyaccountpublickeyxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const tokenAccount = "kta_1dummytokenpublickeyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"; Copy const permissionsToRemove = new Client.lib.Permissions(["ACCESS"]); Copy userClient.updatePermissions( accountToDenyAccess, permissionsToRemove, tokenAccount, Client.lib.Block.AdjustMethod.SUBTRACT, { account: tokenAccount } ); --- # Keeta Network's Advantage | Keeta Network Numbers don't lie. The following reasons are why Keeta Network has the potential to revolutionize blockchain technology: **Scalability**: Keeta Network's enhanced dPoS mechanism provides efficient scalability, enabling it to accommodate the world's financial transactions seamlessly without sacrificing performance or security. **Speed**: Keeta Network is the fastest blockchain in the world, supporting an astonishing 10 million transactions per second. **Energy Consumption**: Many blockchains have struggled with extensive carbon footprints, but Keeta's architecture allows the network to operate at a mere 0.000056 CO2e/transaction. **Low transaction cost**: By utilizing existing cloud infrastructure and providing options for transaction fees in various tokens, it can be more costeffective and cost-predictable. **Security:** With digital identity features and fully consistent writes, Keeta Network ensures secure transactions. **Flexibility:** Multi-token support and robust ability to be updated make Keeta Network adaptable for various applications. **Global Governance:** Its decentralized nature allows for global participation while still adhering to local laws through token-level governance. **Interoperability:** The ability to partition the network into distinct, interoperable subnets allows for greater flexibility and collaboration between different parties. **Regulatory Compliance:** Built-in support for digital identity and sanctioning mechanisms make it easier to comply with existing laws and regulations. [PreviousPrivate Sub Networkchevron-left](https://docs.keeta.com/applications/private-sub-network) [NextResolving the Blockchain Trilemmachevron-right](https://docs.keeta.com/industry-comparison/resolving-the-blockchain-trilemma) --- # Receive | Keeta Network The `receive` operation is used to declare that your account expects to receive a certain token or asset from another account. It’s commonly used in swaps and other multi-party interactions where one party commits to sending something, and the other defines what they want in return. This operator is added to a transaction using a `builder` and is usually paired with a corresponding `send` operation. [hashtag](https://docs.keeta.com/components/blocks/operations/receive#when-to-use) When to Use --------------------------------------------------------------------------------------------------- * Declaring part of a **swap** (e.g., “I send X, and expect to receive Y”) * Defining expected incoming tokens or assets in a contract * Building conditional transactions where value is exchanged [hashtag](https://docs.keeta.com/components/blocks/operations/receive#how-it-works) How it works ----------------------------------------------------------------------------------------------------- When performing a swap, the `send()` operation defines what your account is giving, and the `receive()` operation defines what you expect in return. You create a transaction using both operations, then **compute** the block — but **don’t publish it**. The resulting unsigned block is meant to be sent to the counterparty (e.g. via QR, API, or message). They can then **verify, sign, and publish** the transaction on-chain. Once published with signatures, the swap is finalized. Copy const signer = KeetaNet.lib.Account.fromSeed(DEMO_ACCOUNT_SEED, 0); const client = KeetaNet.UserClient.fromNetwork('test', signer); // Addresses const recipient = KeetaNet.lib.Account.fromPublicKeyString(''); const sendToken = KeetaNet.lib.Account.fromPublicKeyString(''); const receiveToken = KeetaNet.lib.Account.fromPublicKeyString(''); // Amounts (assumes you’ve already fetched decimals and validated) const sendAmount = Numeric.fromDecimalString("10.0", 2); // 10 ABC const receiveAmount = Numeric.fromDecimalString("5.0", 2); // 5 XYZ // Create transaction const builder = client.initBuilder(); builder.send(recipient, sendAmount.valueOf(), sendToken); builder.receive(recipient, receiveAmount.valueOf(), receiveToken, true); // Compute the transaction block (not yet published) const { blocks } = await client.computeBuilderBlocks(builder); // This unsigned block can now be signed and published by the other party const unsignedBytes = blocks[0].toBytes(); console.log("📦 Unsigned swap block ready for signature:", unsignedBytes); [hashtag](https://docs.keeta.com/components/blocks/operations/receive#signature-flow) Signature Flow: ---------------------------------------------------------------------------------------------------------- * You (Party A) compute the transaction with `send()` and `receive()`. * You send the **unpublished block** to Party B (e.g., over API or QR code). * Party B verifies it, signs it, and publishes the transaction to KeetaNet. * Done — the atomic swap is complete! circle-exclamation You **must not publish** the block yourself if you're expecting a counterparty to sign it. The final publish should be done by the party who agrees to the trade — typically the one **receiving the assets**. [PreviousSendchevron-left](https://docs.keeta.com/components/blocks/operations/send) [NextsetInfochevron-right](https://docs.keeta.com/components/blocks/operations/setinfo) Last updated 6 months ago * [When to Use](https://docs.keeta.com/components/blocks/operations/receive#when-to-use) * [How it works](https://docs.keeta.com/components/blocks/operations/receive#how-it-works) * [Signature Flow:](https://docs.keeta.com/components/blocks/operations/receive#signature-flow) --- # Public Network | Keeta Network Keeta Network is available to any party, serving as a hub for innovation and collaboration. The team continues to built the ecosystem with additional tools and protocols to aid participants in taking asset transfers to a new level. With unprecedented performance, interoperability, and real-world applicability, Keeta has set itself up to become an industry leader over the existing public layer-1 blockchain networks. Keeta's use of dPoS as a consensus mechanism provides decentralization by giving all token holders the ability to have an input on the consensus of the network. As the network's participation grows, it becomes more decentralized. Once a transaction is completed, it is broadcasted publicly to the network so any participant can read or audit and transaction. Any person or entity can join the network, and we encourage everyone to do so. [PreviousCreating an Anchorchevron-left](https://docs.keeta.com/features/anchors/creating-an-anchor) [NextPrivate Sub Networkchevron-right](https://docs.keeta.com/applications/private-sub-network) --- # Tokenomics | Keeta Network ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FOnRDl7woCnlKHJiKwTkY%252Ftokenomics-treasury.png%3Falt%3Dmedia%26token%3D4e335075-9a16-4f3c-a113-ee7462ddd379&width=768&dpr=4&quality=100&sign=ebf9dff6&sv=2) ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2FpitcpcamWc0BKEe28I1D%2Fblobs%2FgswPTaV7cqhhyxlK2drB%2Ftoken-graph-unlock.png&width=768&dpr=4&quality=100&sign=1a027f0a&sv=2) [PreviousOfficial Linkschevron-left](https://docs.keeta.com/other-documentation/official-links) [NextRoadmapchevron-right](https://docs.keeta.com/other-documentation/roadmap) Last updated 4 months ago --- # Private Sub Network | Keeta Network Keeta has built the network with real-world applicability in mind. Some specific use cases require a level of privacy that a public network cannot provide. To accommodate this, Keeta Network can be launched in a private setting. Instead of the main network, this is known as a sub network. Sub networks operate identically to the main network, but the transactions are private so they cannot be viewed by main network participants. These networks can be launched in a centralized or decentralized manner, leaving the distribution of power and overall accessibility to be determined by the sub network creator. Accounts from the main network can be transferred to any sub network, allowing users to seamlessly utilize the main network and any relevant sub network with their single universal key pair. Balances can also be transferred between networks, allowing sub network transactions to be reflected on the main network once the accounts are transferred back. [PreviousPublic Networkchevron-left](https://docs.keeta.com/applications/public-network) [NextKeeta Network's Advantagechevron-right](https://docs.keeta.com/industry-comparison/keeta-networks-advantage) --- # modifyTokenBalance | Keeta Network The `modifyTokenBalance()` function lets you **directly adjust a specific account’s balance for a token**, either by adding to or subtracting from it. This is done **from or to the token's "unallocated balance"**, not another user. Think of it like minting or burning — but instead of affecting total supply, you're just updating who holds what. [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#when-to-use) When to Use -------------------------------------------------------------------------------------------------------------- * Mint tokens to an account **(from unallocated token balance)** * Burn tokens from an account **(to unallocated token balance)** * Adjust balance after supply changes * Pre-fill or wipe account balances during setup/testing [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#how-it-works-step-by-step) How It Works (Step-by-Step) -------------------------------------------------------------------------------------------------------------------------------------------- 1 ### [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#choose-a-token) Choose a Token This is the token whose balance is being modified. Copy const tokenAccount = Client.lib.Account.fromPublicKeyString("TOKEN_PUBLIC_KEY") 2 ### [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#choose-a-target-account) Choose a Target Account This is the account receiving or sending the tokens: `userAccount` 3 ### [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#determine-amount) Determine Amount * Use a **positive amount** to credit (add tokens). * Use a **negative amount** to debit (remove tokens). * You can also **overwrite** the balance using `isSet: true`. Copy // Add 1000 tokens const amount = 1000n // OR remove 500 tokens const amount = -500n // OR set balance exactly to 0 const amount = 0n const isSet = true 4 ### [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#call-modifytokenbalance) Call `modifyTokenBalance()` Add the balance operation to the builder. Copy builder.modifyTokenBalance( tokenAccount, amount, isSet ?? false, // optional: true if you want to overwrite balance { account: userAccount } ) 5 ### [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#publish-the-builder) Publish the Builder Finalize the changes by sending them to the network. Copy await userClient.publishBuilder(builder) [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#method) Method ---------------------------------------------------------------------------------------------------- Copy modifyTokenBalance( token: TokenOrPending, amount: bigint, isSet?: boolean, options?: { account: Account } ): void * `amount`: Can be positive (add) or negative (remove) * `isSet`: Default is false. If true, sets the exact balance. Otherwise, adds/subtracts from current balance. * `account`: The target account to modify. [PreviousmodifyTokenSupplychevron-left](https://docs.keeta.com/components/blocks/operations/modifytokensupply) [NextupdatePermissionschevron-right](https://docs.keeta.com/components/blocks/operations/updatepermissions) Last updated 6 months ago * [When to Use](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#when-to-use) * [How It Works (Step-by-Step)](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#how-it-works-step-by-step) * [Choose a Token](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#choose-a-token) * [Choose a Target Account](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#choose-a-target-account) * [Determine Amount](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#determine-amount) * [Call modifyTokenBalance()](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#call-modifytokenbalance) * [Publish the Builder](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#publish-the-builder) * [Method](https://docs.keeta.com/components/blocks/operations/modifytokenbalance#method) --- # Roadmap | Keeta Network ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FY0upCziuVOdgdt5U66vt%252Froadmapv2%2520%283%29.png%3Falt%3Dmedia%26token%3D0dd6ec89-5361-4a83-b92c-596d022f7622&width=768&dpr=4&quality=100&sign=fe2c3693&sv=2) [PreviousTokenomicschevron-left](https://docs.keeta.com/other-documentation/tokenomics) [NextArticleschevron-right](https://docs.keeta.com/other-documentation/articles) Last updated 3 months ago --- # modifyTokenSupply | Keeta Network The `modifyTokenSupply()` operation allows you to **mint** (increase) or **burn** (decrease) the total supply of a token on KeetaNet. This is a low-level supply management tool that modifies the global token supply stored in a given token account. This operation is part of the transaction builder and must be **published** to take effect. [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokensupply#when-to-use) When to Use ------------------------------------------------------------------------------------------------------------- * Minting new tokens to increase supply (e.g. when issuing rewards or enabling inflation). * Burning tokens to reduce supply (e.g. for deflationary models or manual corrections). * Dynamically adjusting circulating supply in response to governance or economic rules. [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokensupply#how-it-works) How It Works --------------------------------------------------------------------------------------------------------------- 1 ### [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokensupply#get-a-token-account) Get a Token Account You need the token account you want to modify. This is usually derived from a known public key. Copy const tokenAccount = Client.lib.Account.fromPublicKeyString(tokenPublicKey) 2 ### [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokensupply#initialize-a-builder) Initialize a Builder Start a transaction builder using `userClient.initBuilder()`. Copy const builder = userClient.initBuilder() 3 ### [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokensupply#call-modifytokensupply) Call `modifyTokenSupply()` Provide an amount and a token account: * Positive values **mint** tokens. * Negative values **burn** tokens. The amount must be an integer or a BigNumber. Copy const builder = userClient.initBuilder() builder.modifyTokenSupply(1000n, { account: tokenAccount }) // Mint 1000 tokens await userClient.publishBuilder(builder) const builder = userClient.initBuilder() builder.modifyTokenSupply(-500n, { account: tokenAccount }) // Burn 500 tokens await userClient.publishBuilder(builder) 4 ### [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokensupply#publish-the-builder) Publish the Builder Send the transaction to the network using `userClient.publishBuilder()` Copy await userClient.publishBuilder(builder) [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokensupply#full-example) Full Example --------------------------------------------------------------------------------------------------------------- Copy // Step 1: Load token account const tokenAccount = Client.lib.Account.fromPublicKeyString(tokenPublicKey) if (!tokenAccount.isToken()) { throw new Error("Invalid token public key") } // Step 2: Start builder const builder = userClient.initBuilder() // Step 3a: Burn 100 tokens builder.modifyTokenSupply(-100n, { account: tokenAccount }) // Step 3b: Or mint 100 tokens builder.modifyTokenSupply(100n, { account: tokenAccount }) // Step 4: Publish the transaction await userClient.publishBuilder(builder) [hashtag](https://docs.keeta.com/components/blocks/operations/modifytokensupply#method) Method --------------------------------------------------------------------------------------------------- [PrevioussetInfochevron-left](https://docs.keeta.com/components/blocks/operations/setinfo) [NextmodifyTokenBalancechevron-right](https://docs.keeta.com/components/blocks/operations/modifytokenbalance) Last updated 6 months ago * [When to Use](https://docs.keeta.com/components/blocks/operations/modifytokensupply#when-to-use) * [How It Works](https://docs.keeta.com/components/blocks/operations/modifytokensupply#how-it-works) * [Get a Token Account](https://docs.keeta.com/components/blocks/operations/modifytokensupply#get-a-token-account) * [Initialize a Builder](https://docs.keeta.com/components/blocks/operations/modifytokensupply#initialize-a-builder) * [Call modifyTokenSupply()](https://docs.keeta.com/components/blocks/operations/modifytokensupply#call-modifytokensupply) * [Publish the Builder](https://docs.keeta.com/components/blocks/operations/modifytokensupply#publish-the-builder) * [Full Example](https://docs.keeta.com/components/blocks/operations/modifytokensupply#full-example) * [Method](https://docs.keeta.com/components/blocks/operations/modifytokensupply#method) Copy modifyTokenSupply( amount: BigNumber | number, options: { account: Account; // The token account whose supply you're modifying } ): void --- # Token Creation | Keeta Network The token creation process on the Keeta network begins with the token creator defining the key attributes of their token. These attributes typically include the token's name, symbol, total supply, and any specific rules or restrictions that will govern the token's behavior on the network. This initial step allows creators to customize their tokens according to their specific needs or use cases. Once the token attributes are defined, the creator initiates a token creation on the Keeta network. If the creation is deemed valid, the network generates a unique identifier for the new token and records its creation on the blockchain. Following this, the network assigns the initial supply to the creator's account. After the token is created and recorded on the blockchain, it becomes part of the Keeta ecosystem. The token creator can distribute, transfer, or manage the tokens according to their intended purpose. The network allows these newly created tokens to interact with other components of the ecosystem, such as exchanges, wallets, or other tokens, subject to the rules and restrictions set during the creation process. It's worth noting that the Keeta network incorporates certain measures to maintain the integrity of the token creation process. These include safeguards to prevent the creation of fraudulent or duplicate tokens, as well as compliance checks to ensure that tokens meet any relevant regulatory requirements, if necessary. Additionally, the network's rules engine allows for the implementation of specific token behaviors, such as automatic burning, minting, or transfer restrictions. These features can be customized during the creation process or modified later, depending on the network's protocols and the specific requirements of the token. [](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FKL7CjkKenzW0LqCxUipy%252Fmint.png%3Falt%3Dmedia%26token%3Dd371eb87-b13f-443a-9ccd-a3d55091e67b&width=490&dpr=4&quality=100&sign=79161168&sv=2) **Mint Tokens** [](https://docs.keeta.com/features/native-tokenization/token-creation/burn-tokens) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FYTXlyg8hoR6kglrh1tuY%252Fburn.png%3Falt%3Dmedia%26token%3Dbecce33d-7681-416a-9a90-2bdd69fc4926&width=490&dpr=4&quality=100&sign=7c258826&sv=2) **Burn Tokens** [](https://docs.keeta.com/features/native-tokenization/token-creation/set-permissions) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FuyI45RtkfIkId71dXd6l%252Fmodify_perm.png%3Falt%3Dmedia%26token%3Dd666c17a-196f-4e45-8e66-12a66d068dd9&width=490&dpr=4&quality=100&sign=93a408a3&sv=2) **Set Permissions** [PreviousNative Tokenizationchevron-left](https://docs.keeta.com/features/native-tokenization) [NextMint Tokenschevron-right](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens) Last updated 4 months ago --- # Resolving the Blockchain Trilemma | Keeta Network Keeta's approach addresses the long-standing blockchain trilemma - the challenge of achieving decentralization, scalability, and security simultaneously. Traditional blockchain networks sacrifice one of these aspects to enhance the others. However, Keeta's DAG structure, combined with its Delegated Proof of Stake (dPoS) consensus mechanism, allows for a harmonious balance of all three elements. The DAG structure provides scalability, while the dPoS system ensures decentralization and security through its validator selection process. [PreviousKeeta Network's Advantagechevron-left](https://docs.keeta.com/industry-comparison/keeta-networks-advantage) [NextTokenizing Real-World Assetschevron-right](https://docs.keeta.com/guides/tokenizing-real-world-assets) --- # Official Links | Keeta Network Discord: [discord.com/invite/keetaarrow-up-right](https://discord.com/invite/keeta) X: [x.com/KeetaNetworkarrow-up-right](https://x.com/KeetaNetwork) Website: [keeta.comarrow-up-right](https://keeta.com/) Whitepaper: [keeta.com/keetanet-whitepaper-20250312.pdfarrow-up-right](https://keeta.com/keetanet-whitepaper-20250312.pdf) Product Manual: [https://keeta.com/product-manual.pdfarrow-up-right](https://keeta.com/product-manual.pdf) SDK Documentation: [static.test.keeta.com/docsarrow-up-right](https://static.test.keeta.com/docs/) ### [hashtag](https://docs.keeta.com/other-documentation/official-links#main-network) Main Network Network Wallet: [wallet.keeta.comarrow-up-right](https://wallet.keeta.com/) Network Block Explorer: [explorer.keeta.comarrow-up-right](https://explorer.keeta.com/) ### [hashtag](https://docs.keeta.com/other-documentation/official-links#test-network) Test Network Test Network Wallet: [wallet.test.keeta.comarrow-up-right](https://wallet.test.keeta.com/) Test Network Block Explorer: [explorer.test.keeta.comarrow-up-right](https://explorer.test.keeta.com/) Test Network Faucet: [faucet.test.keeta.comarrow-up-right](https://faucet.test.keeta.com/) [PreviousDeploying a Nodechevron-left](https://docs.keeta.com/guides/deploying-a-node) [NextTokenomicschevron-right](https://docs.keeta.com/other-documentation/tokenomics) Last updated 3 months ago * [Main Network](https://docs.keeta.com/other-documentation/official-links#main-network) * [Test Network](https://docs.keeta.com/other-documentation/official-links#test-network) --- # Articles | Keeta Network Explore our latest insights and developments related to the Keeta Network. [](https://docs.keeta.com/other-documentation/articles/cryptographically-verifiable-identity-sharing-with-keeta) ![Cover](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2F1876017793-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FpitcpcamWc0BKEe28I1D%252Fuploads%252FN8uaPwyv4FEOJFeCMEjr%252Fcertificate.png%3Falt%3Dmedia%26token%3D7872deda-e6d4-479c-b24b-5420bf17e90c&width=490&dpr=4&quality=100&sign=6e9beebb&sv=2) Cryptographically Verifiable Identity Sharing with Keeta [PreviousRoadmapchevron-left](https://docs.keeta.com/other-documentation/roadmap) [NextCryptographically Verifiable Identity Sharing with Keetachevron-right](https://docs.keeta.com/other-documentation/articles/cryptographically-verifiable-identity-sharing-with-keeta) Last updated 4 months ago --- # Utilizing Identity Profiles | Keeta Network When a user wants to open a new [account](https://docs.keeta.com/components/accounts) with an entity on Keeta Network that requires identity verification, they simply need to provide their [public key](https://docs.keeta.com/components/key-pairs) and the relevant [certificates](https://docs.keeta.com/components/certificates) . The business will then instantly validate the provided certificate(s) and open the new account. This allows the business to effectively verify the user's identity and credentials without the need for a lengthy application process. This system creates a "digital passport", allowing users to carry their verified credentials with them across the Keeta ecosystem in a private and secure manner. It not only simplifies the account opening process but also puts users in control of their own data and privacy. The user only needs to trust one party with their information, which is the CA. Any party that receives the certificate does not recieve the actual personal information, but rather a confirmation that the personal information exists and is sufficient for the action on the network. Users' personal information is no longer being stored across a variety of data servers with unknown security. Moreover, the dynamic nature of these certificates means that if a user's status changes (for example, they move to a new address or obtain a new qualification), this information can be updated in their certificates, ensuring that businesses always have access to the most current and accurate user data when creating new accounts or providing services. ![](https://docs.keeta.com/~gitbook/image?url=https%3A%2F%2Fcontent.gitbook.com%2Fcontent%2FpitcpcamWc0BKEe28I1D%2Fblobs%2FBejbKEXyJNs8enTWtgcV%2Fimage.png&width=768&dpr=4&quality=100&sign=a989df6c&sv=2) With approved certificates, users can effortlessly engage with a variety of entities, streamlining account creation and service access across multiple sectors. [PreviousIdentity Profileschevron-left](https://docs.keeta.com/features/identity-profiles) [NextNative Tokenizationchevron-right](https://docs.keeta.com/features/native-tokenization) Last updated 6 months ago --- # Burn Tokens | Keeta Network Below is a minimal, end-to-end example that mints a token and then burns part of its supply. After creating a token account and minting 10,000 units, a burn operation reduces both the holder’s balance and the token’s total supply by 2,500. Burns are staged with a builder and become final once published. How it works: * Create a token account, set basic info and default permission. * Mint an initial supply to the token account. * Start a new builder to burn: subtract the same amount from the account balance and the total supply. * Publish to commit the burn on-chain. This pattern keeps the ledger consistent: every burned unit is removed from circulation and reflected immediately in both balance and supply.import \* as KeetaNet from "@keetanetwork/keetanet-client"; Copy async function main() { // Generate random seed for account creation const seed = KeetaNet.lib.Account.generateRandomSeed({ asString: true }); console.log("seed =", seed); // Create account and user client const account = KeetaNet.lib.Account.fromSeed(seed, 0); const userClient = KeetaNet.UserClient.fromNetwork("test", account); // Create and mint new token const builderMint = userClient.initBuilder(); const pendingTokenAccount = builderMint.generateIdentifier(KeetaNet.lib.Account.AccountKeyAlgorithm.TOKEN); await builderMint.computeBlocks(); const tokenAccount = pendingTokenAccount.account; builderMint.setInfo( { name: '', description: '', metadata: '', defaultPermission: new KeetaNet.lib.Permissions(['ACCESS']), }, { account: tokenAccount } ); builderMint.modifyTokenSupply(10_000n, { account: tokenAccount }); await builderMint.publish(); console.log("Token account created and minted."); console.log("Balances after minting:", await userClient.allBalances()); // Burn some tokens const builderBurn = userClient.initBuilder(); builderBurn.modifyTokenSupply(-2_500n, { account: tokenAccount }); await builderBurn.publish(); console.log("2,500 tokens burned from account", tokenAccount.publicKeyString.toString()); console.log("Balances after burning:", await userClient.allBalances()); } main() .then(() => { console.log("Done"); process.exit(0); }) .catch((err) => { console.error("Error:", err); process.exit(1); }); [PreviousMint Tokenschevron-left](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens) [NextSet Permissionschevron-right](https://docs.keeta.com/features/native-tokenization/token-creation/set-permissions) Last updated 3 months ago --- # Cryptographically Verifiable Identity Sharing with Keeta | Keeta Network In digital systems, establishing trust between parties often comes down to verifying identity attributes: names, emails, addresses, government IDs, etc. Sharing this data securely, selectively, and in a way that others can verify has long been a challenge—especially when both privacy and integrity are required. Keeta provides a cryptographic framework for identity certification and selective disclosure using X.509 certificates, enhanced with commitment schemes and encrypted containers. This post outlines how it works. ### [hashtag](https://docs.keeta.com/other-documentation/articles/cryptographically-verifiable-identity-sharing-with-keeta#what-is-a-certificate) What Is a Certificate? In cryptographic terms, a certificate is a signed data structure used to assert claims about a subject. One entity (the issuer) attests to attributes of another entity (the subject) by issuing a certificate containing: * The subject’s public key * A set of attributes * The issuer’s digital signature over the certificate’s contents Keeta builds on the standard X.509 certificate format, which is widely used in TLS, PKI systems, and identity infrastructure. X.509 supports an extensions mechanism that allows embedding additional, application-specific data within the certificate. Keeta uses this to encode structured identity attributes in a [consistent, extensible formatarrow-up-right](https://keeta.notion.site/Keeta-KYC-Certificate-Extensions-13e5da848e588042bdcef81fc40458b7) . ### [hashtag](https://docs.keeta.com/other-documentation/articles/cryptographically-verifiable-identity-sharing-with-keeta#sensitive-attributes-and-commitment-schemes) Sensitive Attributes and Commitment Schemes In many cases, identity attributes are privacy-sensitive. Including them in plaintext inside a certificate would expose them to anyone with access to the certificate. Keeta addresses this using a combination of encryption and cryptographic commitments. Specifically: 1. The issuer encrypts the attribute value (e.g., full name, address) and a random salt using the subject’s public key. 2. The issuer computes a commitment in the form of a cryptographic hash over: * the subject's account identifier (public key), * the attribute's cleartext value, * the salt. This commitment is included in the certificate’s extension field, alongside the encrypted value and encrypted salt.This structure enables the following properties: * **Binding**: The commitment ties the attribute to a specific subject and value. * **Hiding**: The actual attribute value and salt remain encrypted. * **Non-repudiation**: The certificate is signed by the issuer and includes the commitment. Because cryptographic hashes are one-way functions, the commitment cannot be reversed to reveal the attribute value, but can be used to verify it when disclosed later. ### [hashtag](https://docs.keeta.com/other-documentation/articles/cryptographically-verifiable-identity-sharing-with-keeta#selective-disclosure-with-encrypted-containers) Selective Disclosure with Encrypted Containers To share specific sensitive attributes with a third party, Keeta uses an "encrypted container." This is a payload encrypted to the public keys of one or more designated recipients.Here’s how the process works at a high level when a user shares attributes via the Keeta Wallet: 1. **Decryption**: 1. The client decrypts each sensitive attribute and its associated salt. 2. **Proof Generation**: 1. For each attribute, the client generates a proof consisting of: * The cleartext value * The salt 3. **Container Construction**: 1. All selected proofs are encrypted into a container using the public keys of the intended recipients. 4. **Link Generation**: 1. The client generates a link referencing: * The encrypted container * The source certificate * The subject's account (public key) 5. **Verification by Recipient**: 1. The recipient decrypts the container, retrieves the proofs, and: * Recomputes the commitment hash for each attribute * Compares it against the commitment embedded in the certificate * Validates that the certificate was issued by a trusted authority This mechanism enables verifiable selective disclosure. Only the recipient can access the attribute value, and they can independently verify that it matches what the issuer originally certified—without needing to trust the subject. [hashtag](https://docs.keeta.com/other-documentation/articles/cryptographically-verifiable-identity-sharing-with-keeta#summary) Summary -------------------------------------------------------------------------------------------------------------------------------------------- Keeta provides a cryptographically robust model for identity certification and sharing: * Attributes are embedded in X.509 certificates using standardized extensions. * Sensitive attributes are encrypted and committed using cryptographic hash functions and salts. * Commitment schemes ensure attribute integrity without exposing values. * Encrypted containers enable secure, recipient-specific selective disclosure. * All proofs are verifiable against the original issuer certificate without relying on out-of-band trust. This architecture supports privacy-preserving identity verification at internet scale, with use cases ranging from fintech onboarding to decentralized identity frameworks. For more technical documentation or to integrate Keeta into your platform, contact our team. [PreviousArticleschevron-left](https://docs.keeta.com/other-documentation/articles) Last updated 4 months ago * [What Is a Certificate?](https://docs.keeta.com/other-documentation/articles/cryptographically-verifiable-identity-sharing-with-keeta#what-is-a-certificate) * [Sensitive Attributes and Commitment Schemes](https://docs.keeta.com/other-documentation/articles/cryptographically-verifiable-identity-sharing-with-keeta#sensitive-attributes-and-commitment-schemes) * [Selective Disclosure with Encrypted Containers](https://docs.keeta.com/other-documentation/articles/cryptographically-verifiable-identity-sharing-with-keeta#selective-disclosure-with-encrypted-containers) * [Summary](https://docs.keeta.com/other-documentation/articles/cryptographically-verifiable-identity-sharing-with-keeta#summary) --- # Mint Tokens | Keeta Network This guide explains how to create and mint a token using the KeetaNet SDK. You'll learn how to build and publish a token account, set its supply, and adjust balances. ### [hashtag](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens#step-by-step-minting-a-token) Step-by-Step 1 ### [hashtag](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens#initialize-the-transaction-builder) Initialize the Transaction Builder Start by creating a transaction builder from your user client. This builder is used to queue up all operations before publishing to the network. Copy const builder = userClient.initBuilder(); 2 ### [hashtag](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens#generate-the-token-account) Generate the Token Account Use the builder to create a new token account: Copy const pendingTokenAccount = builder.generateIdentifier(KeetaNet.lib.Account.AccountKeyAlgorithm.TOKEN); await builder.computeBlocks(); const tokenAccount = pendingTokenAccount.account; console.log("tokenAccount.publicKey =", tokenAccount.publicKeyString.toString()); 3 ### [hashtag](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens#set-token-information-and-permissions) Set Token Information & Permissions Configure the basic information and default permissions for your token: Copy builder.setInfo( { name: '', // Token name description: '', // Short description metadata: '', // Arbitrary metadata defaultPermission: new KeetaNet.lib.Permissions([\ 'ACCESS', // Public token\ ]), }, { account: tokenAccount }, ); 4 ### [hashtag](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens#mint-token-supply) Mint Token Supply Define the total supply for the new token and mint tokens into the liquidity account: Copy builder.modifyTokenSupply(10_000n, { account: tokenAccount }); // Set total supply builder.send(account, 10_000n, tokenAccount, undefined, { account: tokenAccount }); // Distribute token amount to the liquidity account 5 ### [hashtag](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens#publish-the-operation) Publish the Operation Send the queued operations to the network: Copy await builder.publish(); console.log("Token account created and minted."); [hashtag](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens#full-code-example) Full Code Example ---------------------------------------------------------------------------------------------------------------------------------- Copy import * as KeetaNet from "@keetanetwork/keetanet-client"; // Function to create and mint a new token async function createToken(userClient: KeetaNet.UserClient) { const builder = userClient.initBuilder(); // Generate the token account identifier const pendingTokenAccount = builder.generateIdentifier(KeetaNet.lib.Account.AccountKeyAlgorithm.TOKEN); await builder.computeBlocks(); const tokenAccount = pendingTokenAccount.account; // Set token info and permissions builder.setInfo( { name: '', // Token name (add as needed) description: '', // Description (add as needed) metadata: '', // Metadata (add as needed) defaultPermission: new KeetaNet.lib.Permissions([\ 'ACCESS', // Public token\ ]), }, { account: tokenAccount }, ); // Increase (mint) total token supply and distribute the tokens builder.modifyTokenSupply(10_000n, { account: tokenAccount }); builder.send(account, 10_000n, tokenAccount, undefined, { account: tokenAccount }); // Publish the transaction to the network await builder.publish(); console.log("Token account created and minted."); return tokenAccount; } // Main function demonstrating token creation async function main() { // Generate a random seed for account creation const seed = KeetaNet.lib.Account.generateRandomSeed({ asString: true }); console.log("seed =", seed); // Create a liquidity provider account from the seed const liquidityProviderAccount = KeetaNet.lib.Account.fromSeed(seed, 0); // Instantiate a user client connected to the test network const liquidityProviderClient = KeetaNet.UserClient.fromNetwork("test", liquidityProviderAccount); // Create and mint the token const tokenAccount = await createToken(liquidityProviderClient); // Log the token identifier that was created console.log("Token Account =", tokenAccount.publicKeyString.get()); // Log balances of the liquidity provider console.log("liquidityProviderClient.balances[] =", await liquidityProviderClient.allBalances()); } main() .then(() => { console.log("Done"); process.exit(0); }) .catch((err) => { console.error("Error:", err); process.exit(1); }); [PreviousToken Creationchevron-left](https://docs.keeta.com/features/native-tokenization/token-creation) [NextBurn Tokenschevron-right](https://docs.keeta.com/features/native-tokenization/token-creation/burn-tokens) Last updated 3 months ago * [Step-by-Step](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens#step-by-step-minting-a-token) * [Initialize the Transaction Builder](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens#initialize-the-transaction-builder) * [Generate the Token Account](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens#generate-the-token-account) * [Set Token Information & Permissions](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens#set-token-information-and-permissions) * [Mint Token Supply](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens#mint-token-supply) * [Publish the Operation](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens#publish-the-operation) * [Full Code Example](https://docs.keeta.com/features/native-tokenization/token-creation/mint-tokens#full-code-example) --- # Single-Token Storage Account | Keeta Network This example shows how to create a storage account that can only hold one specific type of token. It demonstrates how to set permissions so that the storage account is restricted to receiving and holding only the designated token using the `STORAGE_CAN_HOLD` permission. 1 ### [hashtag](https://docs.keeta.com/components/accounts/storage-accounts/single-token-storage-account#step-1-account-setup-and-initial-state) Account Setup and Initial State This establishes the foundation by generating a random seed and creating a single account that will own the storage account. The code checks for existing storage accounts (initially empty) and connects to the Keeta test network through a user client Copy async function main() { const seed = KeetaNet.lib.Account.generateRandomSeed({ asString: true }); console.log("seed =", seed); const account = KeetaNet.lib.Account.fromSeed(seed, 0); const userClient = KeetaNet.UserClient.fromNetwork("test", account); console.log("account.publicKey =", account.publicKeyString.toString()); console.log("account.storageAccounts[] =", (await userClient.listACLsByPrincipal()).filter(acl => acl.entity.isStorage())); } 2 ### [hashtag](https://docs.keeta.com/components/accounts/storage-accounts/single-token-storage-account#step-2-creating-a-basic-storage-account) Creating a Basic Storage Account This creates a storage account with minimal permissions. The `STORAGE_DEPOSIT` permission allows anyone to deposit tokens into the storage account, but notably missing is `STORAGE_CAN_HOLD`, which means the account cannot actually hold any tokens yet. Copy async function createStorageAccount(userClient: KeetaNet.UserClient) { const builder = userClient.initBuilder(); const pendingStorageAccount = builder.generateIdentifier(KeetaNet.lib.Account.AccountKeyAlgorithm.STORAGE); await builder.computeBlocks(); const storageAccount = pendingStorageAccount.account; builder.setInfo({ name: '', description: '', metadata: '', defaultPermission: new KeetaNet.lib.Permissions(['STORAGE_DEPOSIT']) }, { account: storageAccount }); await userClient.publishBuilder(builder); return storageAccount; } 3 ### [hashtag](https://docs.keeta.com/components/accounts/storage-accounts/single-token-storage-account#step-3-examining-account-state-and-permissions) Examining Account State and Permissions This examines the storage account's Access Control Lists (ACLs) and default permissions. The ACL shows all permission relationships involving the storage account, while the default permissions show what actions are allowed by default (currently only `STORAGE_DEPOSIT`). Copy console.log("storageAccount.acls[] =", (await userClient.listACLsByEntity({ account: storageAccount })).map(acl => ({ entity: acl.entity.publicKeyString.toString(), principal: acl.principal.publicKeyString.toString(), target: acl.target.publicKeyString.toString(), permissions: acl.permissions.base.flags, }))); console.log("storageAccount.defaultPermission =", (await userClient.state({ account: storageAccount })).info.defaultPermission?.base.flags); 4 ### [hashtag](https://docs.keeta.com/components/accounts/storage-accounts/single-token-storage-account#step-4-granting-token-holding-permission) Granting Token Holding Permission This grants the storage account permission to hold the base token (Keeta - KTA). The `STORAGE_CAN_HOLD` permission is added specifically for the base token, allowing the storage account to receive and hold KTA tokens. The `ADD` method appends this permission to existing ones. Copy const tokenAccount = userClient.baseToken; await userClient.updatePermissions( tokenAccount, new KeetaNet.lib.Permissions(['STORAGE_CAN_HOLD']), undefined, KeetaNet.lib.Block.AdjustMethod.ADD, { account: storageAccount } ); 5 ### [hashtag](https://docs.keeta.com/components/accounts/storage-accounts/single-token-storage-account#step-5-verifying-updated-permissions) Verifying Updated Permissions This checks the updated ACL to confirm the new permission has been added. The storage account now has `STORAGE_CAN_HOLD` permission specifically for the base token, allowing it to receive KTA deposits. Copy console.log("storageAccount.acls[] =", (await userClient.listACLsByEntity({ account: storageAccount })).map(acl => ({ entity: acl.entity.publicKeyString.toString(), principal: acl.principal.publicKeyString.toString(), target: acl.target.publicKeyString.toString(), permissions: acl.permissions.base.flags, }))); [hashtag](https://docs.keeta.com/components/accounts/storage-accounts/single-token-storage-account#complete-code-example) Complete Code Example ---------------------------------------------------------------------------------------------------------------------------------------------------- Copy import * as KeetaNet from "@keetanetwork/keetanet-client"; async function createStorageAccount(userClient: KeetaNet.UserClient) { // Initialize the user client builder const builder = userClient.initBuilder(); // Create a new storage account const pendingStorageAccount = builder.generateIdentifier(KeetaNet.lib.Account.AccountKeyAlgorithm.STORAGE); // Compute the pending storage account await builder.computeBlocks(); // Get the storage account const storageAccount = pendingStorageAccount.account; console.log("storageAccount.publicKey =", storageAccount.publicKeyString.toString()); // Setting the storage account default permissions builder.setInfo( { name: '', description: '', metadata: '', defaultPermission: new KeetaNet.lib.Permissions([\ 'STORAGE_DEPOSIT', // Allow everyone to deposit into the storage account\ ]) }, { account: storageAccount } ); // Publish the builder to create the storage account await userClient.publishBuilder(builder); return storageAccount; } async function main() { const seed = KeetaNet.lib.Account.generateRandomSeed({ asString: true }); console.log("seed =", seed); const account = KeetaNet.lib.Account.fromSeed(seed, 0); const userClient = KeetaNet.UserClient.fromNetwork("test", account); console.log("account.publicKey =", account.publicKeyString.toString()); console.log("account.storageAccounts[] =", (await userClient.listACLsByPrincipal()).filter(acl => acl.entity.isStorage())); /** * Create a new storage account with default permissions allowing deposits. * * This will allow anyone to deposit into the storage account, but won't * allow the storage account to hold any tokens. */ const storageAccount = await createStorageAccount(userClient); console.log("storageAccount.publicKey =", storageAccount.publicKeyString.toString()); console.log("storageAccount.acls[] =", (await userClient.listACLsByEntity({ account: storageAccount })).map(acl => ({ entity: acl.entity.publicKeyString.toString(), principal: acl.principal.publicKeyString.toString(), target: acl.target.publicKeyString.toString(), permissions: acl.permissions.base.flags, }))); console.log(""); console.log("storageAccount.defaultPermission =", (await userClient.state({ account: storageAccount })).info.defaultPermission?.base.flags); console.log(""); // Keeta (KTA) base token account const tokenAccount = userClient.baseToken; /** * Add permission to allow the storage account to hold the base token (Keeta - KTA). */ await userClient.updatePermissions( tokenAccount, new KeetaNet.lib.Permissions(['STORAGE_CAN_HOLD']), undefined, KeetaNet.lib.Block.AdjustMethod.ADD, { account: storageAccount } ) console.log("storageAccount.acls[] =", (await userClient.listACLsByEntity({ account: storageAccount })).map(acl => ({ entity: acl.entity.publicKeyString.toString(), principal: acl.principal.publicKeyString.toString(), target: acl.target.publicKeyString.toString(), permissions: acl.permissions.base.flags, }))); /** * If you try to send tokens that are not the base token (KTA) to the storage account, * it will fail with an error: * "XX does not have required permissions to perform action on YY/undefined -- needs [STORAGE_CAN_HOLD, ACCESS]/[]" * * But if you try to send the base token (KTA) to the storage account, it will succeed. */ } main().then(() => { console.log("Done"); process.exit(0); }).catch((err) => { console.error("Error:", err); process.exit(1); }); [PreviousCreate a Storage Accountchevron-left](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account) [NextKey Pairschevron-right](https://docs.keeta.com/components/key-pairs) Last updated 6 months ago * [Account Setup and Initial State](https://docs.keeta.com/components/accounts/storage-accounts/single-token-storage-account#step-1-account-setup-and-initial-state) * [Creating a Basic Storage Account](https://docs.keeta.com/components/accounts/storage-accounts/single-token-storage-account#step-2-creating-a-basic-storage-account) * [Examining Account State and Permissions](https://docs.keeta.com/components/accounts/storage-accounts/single-token-storage-account#step-3-examining-account-state-and-permissions) * [Granting Token Holding Permission](https://docs.keeta.com/components/accounts/storage-accounts/single-token-storage-account#step-4-granting-token-holding-permission) * [Verifying Updated Permissions](https://docs.keeta.com/components/accounts/storage-accounts/single-token-storage-account#step-5-verifying-updated-permissions) * [Complete Code Example](https://docs.keeta.com/components/accounts/storage-accounts/single-token-storage-account#complete-code-example) --- # Deploying a Node | Keeta Network The preferred method for deploying a node is using the Pulumi deployment scripts, which will generate the necessary scalable GCP infrastructure to run a Representative Node. The configuration options can be used to control the components that Pulumi deploys. 1 ### [hashtag](https://docs.keeta.com/guides/deploying-a-node#install-prerequisites) Install Prerequisites 1. Pulumi CLI [https://www.pulumi.com/docs/get-started/install/arrow-up-right](https://www.pulumi.com/docs/get-started/install/) Login is not required, and the deployment process can leverage multiple backends (eg, Google Cloud Bucket or Pulumi Hosted). If you choose to store the stack in a cloud environment, then log in to the preferred provider. 1. Google Cloud CLI [https://cloud.google.com/sdk/docs/installarrow-up-right](https://cloud.google.com/sdk/docs/install) 2. Node JS Version 20.18.0 If using macOS then the following are require prerequisites to compile from source and can be installed with `brew` * jq, coreutils, python 2 ### [hashtag](https://docs.keeta.com/guides/deploying-a-node#clone-the-node-repository) Clone the Node Repository Copy git clone [email protected]:KeetaNetwork/node.git keeta-node cd keeta-node/deployment 3 ### [hashtag](https://docs.keeta.com/guides/deploying-a-node#create-deployment-config) Create Deployment Config Use the example `config/example.json` to set the desired configuration parameters. Copy the example to your desired Pulumi stack name (eg, `config/test.json`) and update the configuration to fit your needs. 4 ### [hashtag](https://docs.keeta.com/guides/deploying-a-node#initialize-pulumi-stack) Initialize Pulumi Stack The deployment is designed to work with a KMS to manage encrypting secrets, such as the SEED used by the Representative for voting and other sensitive data. Here we initialize the Pulumi stack with a KMS. `` should match the name of the configuration file created in the previous step, and the GCPKMS URL should match a KMS created in your GCP Project. Copy pulumi stack init --secrets-provider="gcpkms://projects/

/locations//keyRings//cryptoKeys/" 5 ### [hashtag](https://docs.keeta.com/guides/deploying-a-node#define-gcp-project-for-pulumi) Define GCP Project for Pulumi Define the GCP environment that Pulumi should deploy to. This will add the GCP Project to the Pulumi..yaml file that was initialized in the previous step. Copy config --stack set gcp:project 6 ### [hashtag](https://docs.keeta.com/guides/deploying-a-node#add-encrypted-representative-seed) Add Encrypted Representative SEED Encrypted variables can be added to the Pulumi configuration as secrets, encrypted with the KMS provided earlier. In this case, `KEETANET_LAMBDA_SEED` is the environment variable the node uses along with the index of the Representative from `Regions` in the configuration to compute the private key used for Voting by the Representative. The SEED should be a 32-character hex string. For example, using openssl, a seed could be generated with `openssl rand -hex 32` Copy pulumi config --stack set --secret keetanet-cloud-deploy:KEETANET_LAMBDA_SEED 7 ### [hashtag](https://docs.keeta.com/guides/deploying-a-node#deploy-the-pulumi-stack) Deploy the Pulumi Stack The following command will build the necessary binaries and deploy all of the infrastructure components. Pulumi will display the changes with a prompt to proceed or cancel. Copy make do-deploy [PreviousTokenizing Real-World Assetschevron-left](https://docs.keeta.com/guides/tokenizing-real-world-assets) [NextOfficial Linkschevron-right](https://docs.keeta.com/other-documentation/official-links) Last updated 4 months ago * [Install Prerequisites](https://docs.keeta.com/guides/deploying-a-node#install-prerequisites) * [Clone the Node Repository](https://docs.keeta.com/guides/deploying-a-node#clone-the-node-repository) * [Create Deployment Config](https://docs.keeta.com/guides/deploying-a-node#create-deployment-config) * [Initialize Pulumi Stack](https://docs.keeta.com/guides/deploying-a-node#initialize-pulumi-stack) * [Define GCP Project for Pulumi](https://docs.keeta.com/guides/deploying-a-node#define-gcp-project-for-pulumi) * [Add Encrypted Representative SEED](https://docs.keeta.com/guides/deploying-a-node#add-encrypted-representative-seed) * [Deploy the Pulumi Stack](https://docs.keeta.com/guides/deploying-a-node#deploy-the-pulumi-stack) --- # Tokenizing Real-World Assets | Keeta Network 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 ### [hashtag](https://docs.keeta.com/guides/tokenizing-real-world-assets#prepare-your-accounts) 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) Copy const signer = KeetaNet.lib.Account.fromSeed(DEMO_SEED, 0); const authority = KeetaNet.lib.Account.fromSeed(DEMO_SEED, 1); 2 ### [hashtag](https://docs.keeta.com/guides/tokenizing-real-world-assets#create-metadata-for-your-real-world-asset) 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 Copy 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 ### [hashtag](https://docs.keeta.com/guides/tokenizing-real-world-assets#start-a-transaction-builder) Start a transaction builder This prepares your transaction to include all operations in one publishable bundle. Copy const builder = client.initBuilder(); builder.updateAccounts({ signer, account: signer }); 4 ### [hashtag](https://docs.keeta.com/guides/tokenizing-real-world-assets#create-the-token-account) Create the token account This is where the NFT will live. It’s a new account of type `TOKEN`. Copy const token = builder.generateIdentifier(KeetaNet.lib.Account.AccountKeyAlgorithm.TOKEN); await client.computeBuilderBlocks(builder); // seal block so token exists 5 ### [hashtag](https://docs.keeta.com/guides/tokenizing-real-world-assets#make-it-non-fungible) Make it non-fungible Set the token’s supply to `1`. That means only one account can own this NFT at a time. Copy builder.modifyTokenSupply(1n, { account: token.account }); 6 ### [hashtag](https://docs.keeta.com/guides/tokenizing-real-world-assets#attach-metadata-and-permissions) Attach metadata and permissions Now link your signed metadata to the token, and set permissions so it can be held by any user. Copy builder.setInfo({ name: 'RWA-DEMO', description: 'Token representing a real-world asset', metadata: metadataBase64, defaultPermission: new KeetaNet.lib.Permissions(['ACCESS'], []) }, { account: token.account }); 7 ### [hashtag](https://docs.keeta.com/guides/tokenizing-real-world-assets#publish-the-transaction) Publish the transaction Finalize and submit your transaction to the Keeta Network. Copy 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: Copy console.log('Token address:', token.account.publicKeyString.get()); [hashtag](https://docs.keeta.com/guides/tokenizing-real-world-assets#full-code-example) Full Code Example -------------------------------------------------------------------------------------------------------------- Copy 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); [PreviousResolving the Blockchain Trilemmachevron-left](https://docs.keeta.com/industry-comparison/resolving-the-blockchain-trilemma) [NextDeploying a Nodechevron-right](https://docs.keeta.com/guides/deploying-a-node) Last updated 7 months ago * [Prepare your accounts](https://docs.keeta.com/guides/tokenizing-real-world-assets#prepare-your-accounts) * [Create metadata for your real-world asset](https://docs.keeta.com/guides/tokenizing-real-world-assets#create-metadata-for-your-real-world-asset) * [Start a transaction builder](https://docs.keeta.com/guides/tokenizing-real-world-assets#start-a-transaction-builder) * [Create the token account](https://docs.keeta.com/guides/tokenizing-real-world-assets#create-the-token-account) * [Make it non-fungible](https://docs.keeta.com/guides/tokenizing-real-world-assets#make-it-non-fungible) * [Attach metadata and permissions](https://docs.keeta.com/guides/tokenizing-real-world-assets#attach-metadata-and-permissions) * [Publish the transaction](https://docs.keeta.com/guides/tokenizing-real-world-assets#publish-the-transaction) * [Full Code Example](https://docs.keeta.com/guides/tokenizing-real-world-assets#full-code-example) --- # Create a Storage Account | Keeta Network This example demonstrates how to create tokens, establish shared storage accounts, and manage complex permission scenarios in Keeta. Building on the basic storage account concepts, this code shows a complete workflow involving token creation, liquidity provisioning, and delegated sending capabilities. ### [hashtag](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account#step-by-step) Step by Step 1 ### [hashtag](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account#step-1-initial-setup-and-account-generation) Initial Setup and Account Generation Establish the foundation by generating a random seed and create three accounts: a liquidity provider (index 0), accountA (index 1), and accountB (index 2). Each account connects to the Keeta test network. Copy async function main() { const seed = KeetaNet.lib.Account.generateRandomSeed({ asString: true }); console.log("seed =", seed); // Create liquidity provider account (token creator) const liquidityProviderAccount = KeetaNet.lib.Account.fromSeed(seed, 0); const liquidityProviderClient = KeetaNet.UserClient.fromNetwork("test", liquidityProviderAccount); // Create two user accounts for shared storage const accountA = KeetaNet.lib.Account.fromSeed(seed, 1); const accountB = KeetaNet.lib.Account.fromSeed(seed, 2); const userClientA = KeetaNet.UserClient.fromNetwork("test", accountA); const userClientB = KeetaNet.UserClient.fromNetwork("test", accountB); console.log("accountA.publicKey =", accountA.publicKeyString.toString()); console.log("accountB.publicKey =", accountB.publicKeyString.toString()); } 2 ### [hashtag](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account#step-2-token-creation-and-minting) Token Creation and Minting This creates a new token account using the TOKEN algorithm, sets public access permissions, mints 10,000 tokens, and publishes the token to the blockchain. The liquidity provider becomes the initial holder of all tokens. Copy async function createToken(userClient: KeetaNet.UserClient) { const builder = userClient.initBuilder(); // Create a new token account const pendingTokenAccount = builder.generateIdentifier(KeetaNet.lib.Account.AccountKeyAlgorithm.TOKEN) await builder.computeBlocks(); const tokenAccount = pendingTokenAccount.account; console.log("tokenAccount.publicKey =", tokenAccount.publicKeyString.toString()); // Set token permissions and metadata builder.setInfo({ name: '', description: '', metadata: '', defaultPermission: new KeetaNet.lib.Permissions(['ACCESS']), // Public token }, { account: tokenAccount }); // Mint 10,000 tokens builder.modifyTokenSupply(10_000n, { account: tokenAccount }); builder.modifyTokenBalance(tokenAccount, 10_000n); // Publish to blockchain await userClient.publishBuilder(builder); console.log("Token account created and minted.\n"); return tokenAccount; } // Call the function in main() console.log("\nCreating liquidity provider account and token account..."); const tokenAccount = await createToken(liquidityProviderClient); console.log("liquidityProviderClient.balances[] =", await liquidityProviderClient.allBalances()); 3 ### [hashtag](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account#step-3-storage-account-creation-with-permissions) Storage Account Creation with Permissions This creates a storage account with default permissions allowing token holding and deposits. AccountB receives `SEND_ON_BEHALF` permission, enabling it to send tokens from the storage account without being the owner. Copy // Check initial storage accounts (should be empty) console.log("\nChecking storage accounts before creation:"); console.log("accountA.storageAccounts[] =", (await userClientA.listACLsByPrincipal()).filter(acl => acl.entity.isStorage())); console.log("accountB.storageAccounts[] =", (await userClientB.listACLsByPrincipal()).filter(acl => acl.entity.isStorage())); // Create storage account const builder = userClientA.initBuilder(); const pendingStorageAccount = builder.generateIdentifier(KeetaNet.lib.Account.AccountKeyAlgorithm.STORAGE); await builder.computeBlocks(); const storageAccount = pendingStorageAccount.account; console.log("storageAccount.publicKey =", storageAccount.publicKeyString.toString()); // Set default permissions builder.setInfo({ name: '', description: '', metadata: '', defaultPermission: new KeetaNet.lib.Permissions([\ 'STORAGE_CAN_HOLD', // Allow holding any token\ 'STORAGE_DEPOSIT', // Allow anyone to deposit\ ]) }, { account: storageAccount }); // Grant SEND_ON_BEHALF permission to accountB builder.updatePermissions( accountB, new KeetaNet.lib.Permissions(['SEND_ON_BEHALF']), undefined, undefined, { account: storageAccount } ); // Publish storage account await userClientA.publishBuilder(builder); console.log("Storage account created and permissions updated."); 4 ### [hashtag](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account#step-4-token-distribution) Token Distribution The liquidity provider distributes tokens: 1,000 tokens to the storage account for shared use and 5,000 tokens to accountA for individual use. This creates a realistic shared treasury scenario. Copy // Check balances before distribution console.log("\nChecking balances before deposit:"); console.log("accountA.balances[] =", await userClientA.allBalances()); console.log("accountB.balances[] =", await userClientB.allBalances()); console.log("storageAccount.balances[] =", await userClientA.allBalances({ account: storageAccount })); // Distribute tokens from liquidity provider console.log("\nDepositing tokens from the liquidity provider..."); const builderSend = await liquidityProviderClient.initBuilder(); builderSend.send(storageAccount, 1_000n, tokenAccount); // 1,000 to storage builderSend.send(accountA, 5_000n, tokenAccount); // 5,000 to accountA await liquidityProviderClient.publishBuilder(builderSend); // Check balances after distribution console.log("\nChecking balances after deposit:"); console.log("accountA.balances[] =", await userClientA.allBalances()); console.log("accountB.balances[] =", await userClientB.allBalances()); console.log("storageAccount.balances[] =", await userClientA.allBalances({ account: storageAccount })); 5 ### [hashtag](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account#delegated-operations-using-send_on_behalf) Delegated Operations Using SEND\_ON\_BEHALF AccountB uses its `SEND_ON_BEHALF` permission to send tokens from the storage account: 500 tokens to accountA and 300 tokens to itself. The `{ account: storageAccount }` parameter specifies the source account for delegated operations. Copy // accountB sends tokens from storageAccount using SEND_ON_BEHALF permission await userClientB.send(accountA, 500n, tokenAccount, undefined, { account: storageAccount }); await userClientB.send(accountB, 300n, tokenAccount, undefined, { account: storageAccount }); // Check final balances console.log("\nChecking balances after accountB sends tokens from storageAccount:"); console.log("accountA.balances[] =", await userClientA.allBalances()); console.log("accountB.balances[] =", await userClientB.allBalances()); console.log("storageAccount.balances[] =", await userClientA.allBalances({ account: storageAccount })); This workflow demonstrates how to create a complete token ecosystem with shared storage and delegated permissions, enabling team treasuries, shared wallets, and controlled token distribution systems. [hashtag](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account#full-code-example) Full Code Example ---------------------------------------------------------------------------------------------------------------------------------------- Copy import * as KeetaNet from "@keetanetwork/keetanet-client"; // Token creation function async function createToken(userClient: KeetaNet.UserClient) { const builder = userClient.initBuilder(); // Create a new token account const pendingTokenAccount = builder.generateIdentifier(KeetaNet.lib.Account.AccountKeyAlgorithm.TOKEN) await builder.computeBlocks(); const tokenAccount = pendingTokenAccount.account; console.log("tokenAccount.publicKey =", tokenAccount.publicKeyString.toString()); // Setting the token account default permissions builder.setInfo( { name: '', description: '', metadata: '', defaultPermission: new KeetaNet.lib.Permissions([\ 'ACCESS', // Public token\ ]), }, { account: tokenAccount }, ) // Minting the token builder.modifyTokenSupply(10_000n, { account: tokenAccount }); builder.modifyTokenBalance(tokenAccount, 10_000n) // Publish the blocks await userClient.publishBuilder(builder); console.log("Token account created and minted.\n"); return tokenAccount; } async function main() { const seed = KeetaNet.lib.Account.generateRandomSeed({ asString: true }); console.log("seed =", seed); /** * Creating liquidity provider account and token account */ console.log("\nCreating liquidity provider account and token account..."); const liquidityProviderAccount = KeetaNet.lib.Account.fromSeed(seed, 0); const liquidityProviderClient = KeetaNet.UserClient.fromNetwork("test", liquidityProviderAccount); const tokenAccount = await createToken(liquidityProviderClient); console.log("liquidityProviderClient.balances[] =", await liquidityProviderClient.allBalances()); /** * Creating two user accounts (accountA and accountB) * to demonstrate shared storage account creation. */ const accountA = KeetaNet.lib.Account.fromSeed(seed, 1); const accountB = KeetaNet.lib.Account.fromSeed(seed, 2); const userClientA = KeetaNet.UserClient.fromNetwork("test", accountA); const userClientB = KeetaNet.UserClient.fromNetwork("test", accountB); console.log("\nGetting accounts:"); console.log("accountA.publicKey =", accountA.publicKeyString.toString()); console.log("accountB.publicKey =", accountB.publicKeyString.toString()); /** * Checking owned storage accounts */ console.log("\nChecking storage accounts before creation:"); console.log("accountA.storageAccounts[] =", (await userClientA.listACLsByPrincipal()).filter(acl => acl.entity.isStorage())); console.log("accountB.storageAccounts[] =", (await userClientB.listACLsByPrincipal()).filter(acl => acl.entity.isStorage())); /** * Creating a storage account */ // Initialize the user client builder const builder = userClientA.initBuilder(); // Create a new storage account const pendingStorageAccount = builder.generateIdentifier(KeetaNet.lib.Account.AccountKeyAlgorithm.STORAGE); // Compute the pending storage account await builder.computeBlocks(); // Get the storage account const storageAccount = pendingStorageAccount.account; console.log("storageAccount.publicKey =", storageAccount.publicKeyString.toString()); // Setting the storage account default permissions builder.setInfo({ name: '', description: '', metadata: '', defaultPermission: new KeetaNet.lib.Permissions([\ 'STORAGE_CAN_HOLD', // Allow the storage account to hold any token\ 'STORAGE_DEPOSIT', // Allow everyone to deposit into the storage account\ ]) }, { account: storageAccount }); // Until here, only `accountA` has access to the storageAccount, his permission is "OWNER". /** * Adding permission for `accountB` on the `storageAccount` * * Here we can set "ADMIN" or "SEND_ON_BEHALF" permissions for `accountB`. * "ADMIN" would allow `accountB` to manage the storage account, while * "SEND_ON_BEHALF" would allow `accountB` to send tokens from the storage account */ builder.updatePermissions( accountB, new KeetaNet.lib.Permissions(['SEND_ON_BEHALF']), undefined, undefined, { account: storageAccount } ); // Publish the blocks await userClientA.publishBuilder(builder); console.log("Storage account created and permissions updated."); /** * Checking owned storage accounts */ console.log("\nChecking storage accounts after creation:"); console.log("accountA.storageAccounts[] =", (await userClientA.listACLsByPrincipal()).filter(acl => acl.entity.isStorage()).map(acl => acl.entity.publicKeyString.toString())); console.log("accountB.storageAccounts[] =", (await userClientB.listACLsByPrincipal()).filter(acl => acl.entity.isStorage()).map(acl => acl.entity.publicKeyString.toString())); /** * Checking balances before deposit */ console.log("\nChecking balances before deposit:"); console.log("accountA.balances[] =", await userClientA.allBalances()); console.log("accountB.balances[] =", await userClientB.allBalances()); console.log("accountA.storageAccount.balances[] =", await userClientA.allBalances({ account: storageAccount })); console.log("accountB.storageAccount.balances[] =", await userClientB.allBalances({ account: storageAccount })); /** * Depositing tokens from the liquidity provider * LP -> SEND 1_000 -> storageAccount * LP -> SEND 5_000 -> accountA */ console.log("\nDepositing tokens from the liquidity provider..."); const builderSend = await liquidityProviderClient.initBuilder(); builderSend.send(storageAccount, 1_000n, tokenAccount); builderSend.send(accountA, 5_000n, tokenAccount); await liquidityProviderClient.publishBuilder(builderSend); /** * Checking balances after deposit */ console.log("\nChecking balances after deposit:"); console.log("accountA.balances[] =", await userClientA.allBalances()); console.log("accountB.balances[] =", await userClientB.allBalances()); console.log("accountA.storageAccount.balances[] =", await userClientA.allBalances({ account: storageAccount })); console.log("accountB.storageAccount.balances[] =", await userClientB.allBalances({ account: storageAccount })); /** * Depositing tokens from the storage account * accountB using storageAccount -> SEND 500 -> accountA * accountB using storageAccount -> SEND 300 -> accountB */ await userClientB.send(accountA, 500n, tokenAccount, undefined, { account: storageAccount }); await userClientB.send(accountB, 300n, tokenAccount, undefined, { account: storageAccount }); console.log("\nChecking balances after accountB sends 500 tokens from storageAccount to accountA:"); console.log("accountA.balances[] =", await userClientA.allBalances()); console.log("accountB.balances[] =", await userClientB.allBalances()); console.log("accountA.storageAccount.balances[] =", await userClientA.allBalances({ account: storageAccount })); console.log("accountB.storageAccount.balances[] =", await userClientB.allBalances({ account: storageAccount })); } main().then(() => { console.log("Done"); process.exit(0); }).catch((err) => { console.error("Error:", err); process.exit(1); }); [PreviousStorage Accountschevron-left](https://docs.keeta.com/components/accounts/storage-accounts) [NextSingle-Token Storage Accountchevron-right](https://docs.keeta.com/components/accounts/storage-accounts/single-token-storage-account) Last updated 5 months ago * [Step by Step](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account#step-by-step) * [Initial Setup and Account Generation](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account#step-1-initial-setup-and-account-generation) * [Token Creation and Minting](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account#step-2-token-creation-and-minting) * [Storage Account Creation with Permissions](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account#step-3-storage-account-creation-with-permissions) * [Token Distribution](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account#step-4-token-distribution) * [Delegated Operations Using SEND\_ON\_BEHALF](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account#delegated-operations-using-send_on_behalf) * [Full Code Example](https://docs.keeta.com/components/accounts/storage-accounts/create-a-storage-account#full-code-example) --- # Email Protection | Cloudflare Please enable cookies. Email Protection ================ You are unable to access this email address docs.keeta.com ---------------------------------------------------------- The website from which you got to this page is protected by Cloudflare. Email addresses on that page have been hidden in order to keep them from being accessed by malicious bots. **You must enable Javascript in your browser in order to decode the e-mail address**. If you have a website and are interested in protecting it in a similar way, you can [sign up for Cloudflare](https://www.cloudflare.com/sign-up?utm_source=email_protection) . * [How does Cloudflare protect email addresses on website from spammers?](https://developers.cloudflare.com/waf/tools/scrape-shield/email-address-obfuscation/) * [Can I sign up for Cloudflare?](https://developers.cloudflare.com/fundamentals/setup/account/create-account/) Cloudflare Ray ID: **9bfdf353cba21eda** • Your IP: Click to reveal 54.237.218.47 • Performance & security by [Cloudflare](https://www.cloudflare.com/5xx-error-landing) --- # generateIdentifier | Keeta Network The ‎`generateIdentifier()` operation creates a new identifier for an account or asset, such as a network, token, or storage entity. This function is typically used when initializing new assets or accounts that require a unique identifier on the Keeta Network. This operation is part of the ‎\`builder\` and is added to a transaction before publishing. [hashtag](https://docs.keeta.com/components/blocks/operations/generateidentifier#when-to-use) When to Use -------------------------------------------------------------------------------------------------------------- * Creating a new token, network, or storage account * Assigning a unique identifier to a new asset * Initializing accounts before attaching metadata or permissions [hashtag](https://docs.keeta.com/components/blocks/operations/generateidentifier#when-to-use-it) When to Use It? --------------------------------------------------------------------------------------------------------------------- * Ensuring each asset or account has a unique and valid identifier * Streamlining the creation of new entities on the network [hashtag](https://docs.keeta.com/components/blocks/operations/generateidentifier#example-creating-a-new-token-account-with-generateidentifier-and-setting-info) Example; Creating a new token account with generateIdentifier and setting info --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Here’s a simplified example using the transaction builder. See the ‘[Tokenizing Real-World Assets](https://docs.keeta.com/guides/tokenizing-real-world-assets) ’ section for a full implementation, Copy // Step 1: Generate a new token identifier with custom options const pendingAccount = builder.generateIdentifier('TOKEN', { owner: user.account, // Assign the initial owner of the token symbol: 'DEMO', // Token symbol decimals: 2, // Number of decimal places metadata: { category: 'Real World Asset', createdBy: 'Demo Script' } }); // Step 2: Prepare base64-encoded metadata (for demonstration) const assetInfo = { assetType: 'Real World Asset', issuer: 'Demo Organization', issuedAt: new Date().toISOString() }; const metadata_base64 = Buffer.from(JSON.stringify(assetInfo)).toString('base64'); // Step 3: Attach info and default permissions to the new token account builder.setInfo({ name: 'DEMORWA', description: 'Demo Token for Real World Asset', metadata: metadata_base64, // base64-encoded JSON with asset info + signature defaultPermission: newKeetaNet.lib.Permissions(['ACCESS'], []) }, { account: pendingAccount.account // The account you're attaching this info to }); * ‎type – The category of identifier to generate. Can be ‎\`NETWORK\`, ‎\`TOKEN\`, or ‎\`STORAGE\`. * ‎options – (Optional) Additional parameters to customize the identifier generation. * Returns – A ‎\`PendingAccount\` object representing the newly created identifier. Last updated 6 months ago * [When to Use](https://docs.keeta.com/components/blocks/operations/generateidentifier#when-to-use) * [When to Use It?](https://docs.keeta.com/components/blocks/operations/generateidentifier#when-to-use-it) * [Example; Creating a new token account with generateIdentifier and setting info](https://docs.keeta.com/components/blocks/operations/generateidentifier#example-creating-a-new-token-account-with-generateidentifier-and-setting-info) ---