> For the complete documentation index, see [llms.txt](https://developer.1moneynetwork.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.1moneynetwork.com/core-concepts/account-model.md).

# 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:])
}
```
