# Account Model

1Money implements an Account Model (vs UTXO) for its ledger, where, aside from asset positions, also contains properties governing different issuance functions. Account types include:

* [StateAccount](#stateaccount)
* [MintAccount](#mintaccount)
* [TokenAccount](#tokenaccount)

### Account Types

#### StateAccount

StateAccount represents a standard user account that can participate in regular transactions.&#x20;

Key Properties:

* Nonce: A counter that increments with each transaction to prevent replay attacks

Use Cases:

* Serving as the base account type for users to manage their token holdings

***

#### MintAccount

Mint accounts are specialized accounts that control the creation and management of tokens in the system. They represent the authority over a specific token type.

Key Properties:

* Nonce: A counter for transaction sequencing
* Token metadata and configuration
* Authority information

Use Cases:

* Creating new tokens
* Minting additional token supply
* Managing token authorities
* Updating token metadata
* Pausing/unpausing token transfers

***

#### TokenAccount

TokenAccount represents an account that holds a specific token type. It tracks the ownership and balance of tokens for a particular user.

{% hint style="success" %}
You should be able to derive your token account based on your state account and mint account
{% endhint %}

Key Properties:

* Mint: Address of the mint that issued this token
* Amount: The token balance
* Owner: Address of the account that owns these tokens

Use Cases:

* Holding token balances
* Transferring tokens between users
* Tracking token ownership

***

{% hint style="info" %}

## Sample code of Typescript how to derive token account from state account and mint account

{% endhint %}

```typescript
import { keccak256, hexToBytes, stringToBytes, bytesToHex } from 'viem';
export type Address = `0x${string}`;
/**
 * Derives the token account address given the wallet address and mint address.
 * 
 * Address is 20 byte, 160 bits. Let's say if we want to support 50 billion
 * accounts on 1money. That's about 36 bits. There are 124 bits remaining. In
 * other words, the collision probability is 1/2^124, which is very very low.
 * So, we will be fine to just use the hash of the wallet address and mint
 * address to derive the token account address.
 * 
 * @param walletAddress - The wallet address (20 bytes)
 * @param mintAddress - The mint address (20 bytes)
 * @returns The derived token account address
 */
export function deriveTokenAddress(
  walletAddress: string,
  mintAddress: string,
): Address {
  const walletBytes: Uint8Array = walletAddress.startsWith('0x')
    ? hexToBytes(walletAddress as Address)
    : stringToBytes(walletAddress);
  const mintBytes: Uint8Array = mintAddress.startsWith('0x')
    ? hexToBytes(mintAddress as Address)
    : stringToBytes(mintAddress);
  const combined = new Uint8Array(walletBytes.length + mintBytes.length);
  combined.set(walletBytes, 0);
  combined.set(mintBytes, walletBytes.length);
  const hashHex = keccak256(combined);
  const hashBytes = hexToBytes(hashHex);
  const addressBytes = hashBytes.slice(12);
  return bytesToHex(addressBytes) as Address;
}
```

{% hint style="info" %}

## Sample code of Go how to derive token account from state account and mint account

{% endhint %}

```go
import (
    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/crypto"
)

// DeriveTokenAccountAddress derives the token account address given the wallet address and mint address.
// 
// Address is 20 byte, 160 bits. Let's say if we want to support 50 billion
// accounts on 1money. That's about 36 bits. There are 124 bits remaining. In
// other words, the collision probability is 1/2^124, which is very very low.
// So, we will be fine to just use the hash of the wallet address and mint
// address to derive the token account address.
func DeriveTokenAccountAddress(walletAddress common.Address, mintAddress common.Address) common.Address {
    // Concatenate wallet address and mint address bytes
    buf := append(walletAddress.Bytes(), mintAddress.Bytes()...)
    
    // Calculate keccak256 hash
    hash := crypto.Keccak256(buf)
    
    // Return the last 20 bytes of the hash as the token account address
    return common.BytesToAddress(hash[12:])
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developer.1moneynetwork.com/core-concepts/account-model.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
