# Introduction

Welcome to Graphite’s developer documentation hub. Dive into our resources to learn more about the blockchain leading the next generation of consumer crypto.

## Get started with Graphite

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:green;"><strong>Connect to Graphite</strong></mark></td><td>Connect your wallet or development environment to Graphite.</td><td><a href="/pages/JjjojIyKxaiBPzzLwvtg">/pages/JjjojIyKxaiBPzzLwvtg</a></td></tr><tr><td><mark style="color:green;"><strong>Building on Graphite</strong></mark></td><td>Start developing smart contracts or applications on Graphite.</td><td><a href="/pages/7aUFmnCMx9m4smGncsXL">/pages/7aUFmnCMx9m4smGncsXL</a></td></tr><tr><td><mark style="color:green;"><strong>Graphite Node</strong></mark> </td><td>Setup guide for the Graphite testnet, your gateway to seamless dApp integration.</td><td><a href="/pages/QwHFLVleY7QejI9V4gc3">/pages/QwHFLVleY7QejI9V4gc3</a></td></tr></tbody></table>

## Ecosystem Graphite

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-type="content-ref"></th><th data-hidden data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:green;"><strong>Graphite Wallet</strong></mark>  </td><td>Discover the Graphite Wallet, your key to the Graphite ecosystem.</td><td><a href="/pages/1VF0QsFd8zrd2Xjc7dps">/pages/1VF0QsFd8zrd2Xjc7dps</a></td><td></td><td><a href="/pages/1VF0QsFd8zrd2Xjc7dps">/pages/1VF0QsFd8zrd2Xjc7dps</a></td></tr><tr><td><mark style="color:green;"><strong>The Graphite Explorer</strong></mark></td><td>View blocks, transactions, tokens, and more on the Graphite Explorer.</td><td><a href="/pages/guKks9PgI00Qe4YwM2t5">/pages/guKks9PgI00Qe4YwM2t5</a></td><td></td><td><a href="/pages/guKks9PgI00Qe4YwM2t5">/pages/guKks9PgI00Qe4YwM2t5</a></td></tr></tbody></table>


# What is Graphite?

Graphite is a finance-oriented blockchain platform aiming to formalize crypto transactions through a unique reputation-based system, enhanced Know Your Customer (KYC) procedures, and a Proof-of-Authority (PoA) consensus model. Graphite seeks to blend the benefits of traditional financial systems with the transparency and security of blockchain, balancing privacy with a reputation-focused ecosystem.

## **Key Features and Principles**

### **Reputation-Based Ecosystem:**

Graphite’s primary differentiator is it's <mark style="color:green;">**`reputation-centric`**</mark> approach, which enables more formalized, trust-based interactions:

* <mark style="color:green;">**`Account Activation`**</mark>: To avoid clutter from inactive or fraudulent accounts, users activate their wallets with a small fee before sending transactions.
* <mark style="color:green;">**`Trust Score`**</mark>: Each user is assigned a Trust Score, influenced by factors like KYC, account longevity, transaction history, and volume. This score assists in evaluating a user’s credibility, enhancing trust within the ecosystem.

### **Advanced KYC and Privacy Controls**:

* <mark style="color:green;">**`KYC Verification`**</mark>: Graphite offers a KYC verification process that allows users to build their reputations without compromising personal privacy. Verified data remains off-chain and only a user’s KYC level is recorded on the blockchain.
* <mark style="color:green;">**`Zero Knowledge Proof (ZKP) for Enhanced Privacy`**</mark>: Through ZKP technology, Graphite plans to implement KYC procedures that confirm identity without revealing sensitive data, thus ensuring security and privacy.
* <mark style="color:green;">**`KYC Transaction Filters`**</mark>: Users can apply KYC-based filters to incoming transactions, allowing them to block transactions from accounts without KYC. This feature minimizes fraud risks by reinforcing the “One User, One Account” policy.

### **Proof-of-Authority (PoA) with Polymer 2.0 Algorithm**:

* Graphite’s <mark style="color:green;">**`PoA consensus mechanism`**</mark> improves efficiency by using a set of authorized nodes to validate blocks, minimizing computational and energy costs associated with traditional Proof-of-Work systems.
* <mark style="color:green;">**`Top-Tier Authorized Nodes`**</mark>: Top-performing nodes are given priority in block validation, incentivizing high performance. These nodes have twice the likelihood of sealing a block, earning a share of transaction fees.
* <mark style="color:green;">**`Oracle-Based Randomization`**</mark>: To select block sealers fairly, Graphite uses an Oracle system that provides randomized values for each block, ensuring impartiality and reducing potential for collusion.

### **Income Generation for Network Nodes**:

* <mark style="color:green;">**`Transport Nodes`**</mark>: Graphite allows entry-point transport nodes to earn income, setting it apart from most blockchains. A portion of transaction fees goes to these nodes when users initiate transactions through them, enhancing incentives for participation without heavy resource requirements.
* <mark style="color:green;">**`Graphite Foundation Nodes`**</mark>: Maintained by the Graphite Foundation, these nodes provide stability, ensuring uptime and network reliability even if other nodes fail.

### **Efficient Transaction and Fee Model**:

* <mark style="color:green;">**`Fixed Transaction Fees`**</mark>: Graphite applies a consistent fee rate, protecting users from fluctuating gas prices and reducing transaction delays.
* <mark style="color:green;">**`Scalability`**</mark>: The network supports high throughput, handling up to 1,400 transactions per second, with confirmation times under 10 seconds, ensuring speed and reliability.


# Connect to Graphite

Add Graphite to your wallet or development environment to get started.

Use the information below to connect and submit transactions to Graphite.

## [​](https://docs.abs.xyz/overview#testnet)Testnet <a href="#testnet" id="testnet"></a>

<table><thead><tr><th width="184">Property</th><th>Description</th></tr></thead><tbody><tr><td>Name</td><td>Graphite Testnet</td></tr><tr><td>Chain ID</td><td><mark style="color:green;"><strong><code>54170</code></strong></mark></td></tr><tr><td>Chain Name</td><td><mark style="color:green;"><strong><code>"Graphite"</code></strong></mark></td></tr><tr><td>RPC URL</td><td><mark style="color:green;"><strong>https://anon-entrypoint-test-1.atgraphite.com</strong></mark></td></tr><tr><td>WS</td><td><mark style="color:green;"><strong>wss://ws-anon-entrypoint-test-1.atgraphite.com</strong></mark></td></tr><tr><td>Explorer</td><td><a href="https://test.atgraphite.com/"><mark style="color:green;"><strong>test.atgraphite.com</strong></mark></a></td></tr><tr><td>Explorer API</td><td><mark style="color:green;"><strong>api.test.atgraphite.com/api</strong></mark></td></tr><tr><td>Currency Symbol</td><td>@G</td></tr></tbody></table>

Once connected, use a [<mark style="color:green;">**`faucet`**</mark>](https://faucet.atgraphite.com/) to get testnet funds on your wallet.

## Mainnet <a href="#mainnet" id="mainnet"></a>

<table><thead><tr><th width="184">Property</th><th>Description</th></tr></thead><tbody><tr><td>Name</td><td>Graphite Mainnet</td></tr><tr><td>Chain ID</td><td><mark style="color:green;"><strong><code>440017</code></strong></mark></td></tr><tr><td>Chain Name</td><td><mark style="color:green;"><strong><code>"Graphite"</code></strong></mark></td></tr><tr><td>RPC URL</td><td><mark style="color:green;"><strong>https://anon-entrypoint-1.atgraphite.com</strong></mark></td></tr><tr><td>WS</td><td><mark style="color:green;"><strong>wss://ws-anon-entrypoint-1.atgraphite.com</strong></mark></td></tr><tr><td>Explorer</td><td><a href="https://main.atgraphite.com/"><mark style="color:green;"><strong>main.atgraphite.com</strong></mark></a></td></tr><tr><td>Explorer API</td><td><mark style="color:green;"><strong>api.main.atgraphite.com/api</strong></mark></td></tr><tr><td>Currency Symbol</td><td>@G</td></tr></tbody></table>


# Graphite account activation

## Account Activation Instructions&#x20;

### With MetaMask

You can activate your account by following [<mark style="color:green;">**`this link`**</mark>](https://atgraphite.com/account).

{% stepper %}
{% step %}
**Connect MetaMask**&#x20;

* Open MetaMask and select the address you want to connect.
* A pop-up will appear with the message <mark style="color:green;">**`isn't connected to atgraphite.com`**</mark> and a <mark style="color:green;">**`Connect Account`**</mark> button. Click this button to connect the selected address.
  {% endstep %}

{% step %}
**Activate Your Account**

* In the interface, find the <mark style="color:green;">**`Graphite Account`**</mark> card.
* Click the <mark style="color:green;">**`Activate`**</mark> button.&#x20;

*A transaction will be required to activate the account, so make sure you have sufficient funds in your wallet.*

<img src="/files/EweBFaQyGF1kcIudDnlE" alt="" data-size="original">
{% endstep %}

{% step %}
**Confirm the Transaction**

You will be redirected back to MetaMask to confirm the transaction. Approve it in the MetaMask window.
{% endstep %}

{% step %}
**Activation Pending**

After successful confirmation, your account status will change to <mark style="color:green;">**`Pending`**</mark>. This indicates that the request is processing, and the activation should only take a short time.

<img src="/files/OULdA0Hq4U4Qy9A2Cd69" alt="" data-size="original">
{% endstep %}

{% step %}
**Account Activated**

Once the processing is complete, your status will change to <mark style="color:green;">**`Activated`**</mark>. Now you can customize your filters and pass KYC.

<img src="/files/IjnDKvCDbkbAzLtvItx8" alt="" data-size="original">
{% endstep %}
{% endstepper %}

### With Graphite Wallet

{% stepper %}
{% step %}
**Install Graphite Wallet**

* Install Graphite Wallet extension by following [<mark style="color:green;">**`this link`**</mark>](https://chromewebstore.google.com/detail/graphite-wallet/fbgdgmhhhlimaanngeakidegojjbbbbm).
* Create a new wallet or import mnemonic/private key, and come up with a password.
* Supported browser: <mark style="color:green;">**`Chrome`**</mark>
  {% endstep %}

{% step %}
**Completion of Setup**

* Go to the account settings page to activate your account.&#x20;
* A transaction will be required to activate the account, so make sure you have sufficient funds in your wallet.

<figure><img src="/files/Rnx4yM40HMCeCa0gLpWG" alt="" width="185"><figcaption></figcaption></figure>
{% endstep %}

{% step %}
**Activate Your Account**

* In the interface, find the <mark style="color:green;">**`Not activated`**</mark> card. Click on it, and you will be taken to the activation page.
* Click the <mark style="color:green;">**`Activate`**</mark> button.&#x20;

<div><figure><img src="/files/JUnPOCtInz6iZBtPlt4x" alt="" width="185"><figcaption></figcaption></figure> <figure><img src="/files/bpSSKEpktvQm7r7KdLjY" alt="" width="186"><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}
**Confirm the Transaction**

To activate your account, review the transaction details in the next step and confirm it. The process is quick, and your account will be ready to use soon.

<div align="center"><figure><img src="/files/MOu9ugyRJaW0K38yzrfN" alt="" width="185"><figcaption></figcaption></figure> <figure><img src="/files/32gStNA0Ws1lZBY2MDu8" alt="" width="186"><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}
**Waiting for Transaction Confirmation**

After confirming the transaction, please wait for it to be processed. This usually takes only a short time. Once completed, your account will be activated automatically.

<div align="center"><figure><img src="/files/VPpH8zyvtsHPKFmlZVNp" alt="" width="186"><figcaption></figcaption></figure> <figure><img src="/files/nhLeDuAjPqeEr0InROoq" alt="" width="185"><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}
**Account Activated**

Once the processing is complete, your status will change to <mark style="color:green;">**`Activated`**</mark>. Now you can customize your filters and pass KYC.

<div align="center"><figure><img src="/files/AH5vp09afbVa4mvnA47R" alt="" width="185"><figcaption></figcaption></figure></div>
{% endstep %}
{% endstepper %}


# Graphite Wrapped Tokens

These are the addresses of the token and the bridge.

### Mainnet

All tokens have the symbol @G.

<table><thead><tr><th width="138">Network</th><th width="125">Name</th><th>Contract</th></tr></thead><tbody><tr><td>Graphite</td><td>WG@G</td><td><a href="https://main.atgraphite.com/token/0xd766ea5e716bbbc8b7185d176def07124c7a89ec/contract"><mark style="color:green;"><strong><code>0xd766eA5e716bbbC8b7185d176dEf07124c7a89EC</code></strong></mark></a></td></tr><tr><td>Ethereum</td><td>G@ETH</td><td><a href="https://etherscan.io/token/0x440017A1b021006d556d7fc06A54c32E42Eb745B"><mark style="color:green;"><strong><code>0x440017A1b021006d556d7fc06A54c32E42Eb745B</code></strong></mark></a></td></tr><tr><td>Binance</td><td>G@BSC</td><td><a href="https://bscscan.com/token/0x440017A1b021006d556d7fc06A54c32E42Eb745B"><mark style="color:green;"><strong><code>0x440017A1b021006d556d7fc06A54c32E42Eb745B</code></strong></mark></a></td></tr><tr><td>Arbitrum</td><td>G@ARB</td><td><a href="https://arbiscan.io/token/0x440017A1b021006d556d7fc06A54c32E42Eb745B"><mark style="color:green;"><strong><code>0x440017A1b021006d556d7fc06A54c32E42Eb745B</code></strong></mark></a></td></tr><tr><td>Polygon</td><td>G@POL</td><td><a href="https://polygonscan.com/token/0x440017A1b021006d556d7fc06A54c32E42Eb745B"><mark style="color:green;"><strong><code>0x440017A1b021006d556d7fc06A54c32E42Eb745B</code></strong></mark></a></td></tr></tbody></table>

### Testnet

All tokens have the symbol @G.

<table><thead><tr><th width="186">Network</th><th width="105">Name</th><th>Contract</th></tr></thead><tbody><tr><td>Graphite Testnet</td><td>WG@G</td><td><a href="https://test.atgraphite.com/token/0x7d08e44489b64650d950b47fe38b68f091e6dab9/contract"><mark style="color:green;"><strong><code>0x7d08e44489b64650d950B47Fe38b68F091E6dab9</code></strong></mark></a></td></tr><tr><td>Ethereum Sepolia</td><td>G@ETH</td><td><a href="https://sepolia.etherscan.io/token/0x40a74AEe5b64f5A16A3F7Ea182DF9e1e24F387a8"><mark style="color:green;"><strong><code>0x40a74AEe5b64f5A16A3F7Ea182DF9e1e24F387a8</code></strong></mark></a></td></tr><tr><td>Binance Testnet</td><td>G@BSC</td><td><a href="https://testnet.bscscan.com/token/0x92AfaABDCcd3397f5C9261041E2E8d693Fabfa80"><mark style="color:green;"><strong><code>0x92AfaABDCcd3397f5C9261041E2E8d693Fabfa80</code></strong></mark></a></td></tr><tr><td>Arbitrum Sepolia</td><td>G@ARB</td><td><a href="https://sepolia.arbiscan.io/token/0x92AfaABDCcd3397f5C9261041E2E8d693Fabfa80"><mark style="color:green;"><strong><code>0x92AfaABDCcd3397f5C9261041E2E8d693Fabfa80</code></strong></mark></a></td></tr><tr><td>Polygon Amoy</td><td>G@POL</td><td><a href="https://amoy.polygonscan.com/token/0xbe49fe06c2743eeb08598a712b27094a6d6bd6f1"><mark style="color:green;"><strong><code>0xBe49fE06c2743eeB08598A712b27094a6d6Bd6F1</code></strong></mark></a></td></tr></tbody></table>

### Mainnet Bridge

You can use our official interface at [<mark style="color:green;">https://bridge.atgraphite.com</mark>](https://bridge.atgraphite.com/).\
If you prefer to use the bridge functionality without our frontend, follow the instructions below based on your current network to transfer Graphite tokens from one chain to another.

#### On the Graphite Network

Use the <mark style="color:green;">**`swap`**</mark> function:

```solidity
function swap(address to, uint256 destChainId) external payable
```

{% hint style="warning" %}
This is a <mark style="color:green;">`payable`</mark> function — make sure to send the desired amount of native Graphite (@G) along with the transaction.
{% endhint %}

Parameters:

| Name          | Type      | Description                                                                            |
| ------------- | --------- | -------------------------------------------------------------------------------------- |
| `to`          | `address` | Address on the destination chain to receive the tokens                                 |
| `destChainId` | `uint256` | Destination chain ID (`1` = Ethereum, `56` = BSC, `137` = Polygon, `42161` = Arbitrum) |

#### On Other Networks

Use the <mark style="color:green;">**`swapToken`**</mark> function:

```solidity
function swapToken(address to, uint256 destChainId, uint256 amount) external
```

Parameters:

| Name          | Type      | Description                                                                                                 |
| ------------- | --------- | ----------------------------------------------------------------------------------------------------------- |
| `to`          | `address` | Address on the destination chain to receive the tokens                                                      |
| `destChainId` | `uint256` | Destination chain ID (`1` = Ethereum, `56` = BSC, `137` = Polygon, `42161` = Arbitrum, `440017` = Graphite) |
| `amount`      | `uint256` | Amount of Graphite tokens to send (18 decimals)                                                             |

\
The contract code and full documentation are available at: [<mark style="color:green;">https://github.com/atgraphite/graphite-token</mark>](https://github.com/atgraphite/graphite-token)\
\
You can find the documentation for all available contract methods here: [<mark style="color:green;">https://github.com/atgraphite/graphite-token/blob/main/docs/LiquidityStorager.md</mark>](https://github.com/atgraphite/graphite-token/blob/main/docs/LiquidityStorager.md)


# Getting started

Graphite’s Ethereum-compatible VM makes migrating your project onto GRAPHITE very easy. Learn how to interact with Graphite and get all the resources needed to help you get started.

## Why build on Graphite?

The Graphite network offers unparalleled opportunities for developers. With easy contract deployment and a fast TPS rate, you will be able to scale your protocol in no time. Without having to deal with scalability issues, the stage is set for mutually beneficial cooperation.

* EVM compatibility
* Speed
* Users inflow
* Legal cashflows
* Security
* Scalability

## Resources & Learning

The Graphite network is EVM-compatible, so previous experience with Solidity can be applied to our new infrastructure. To start out, review our Developer Documentation. It will help you assess the prospects and potential benefits for your project on the Graphite network.

## Node Setup

[<mark style="color:green;">**`Graphite node setup`**</mark>](/infrastructure/images-and-media) is effortless and can be done with just a couple lines of code thanks to Docker.

{% hint style="danger" %}
Always have a copy of the blockchain saved locally, parse data and test whatever and whenever you want.
{% endhint %}

## Graphite JS SDK

We adopted the Web3JS library to make your interaction with Graphite blockchain as easy as possible, regardless of scale. Connect your wallet and get access to all the features the Web3JS library has, along with new ones introduced by Graphite Network.

## Graphite Explorer

We’ve created [<mark style="color:green;">**`the Graphite Explorer`**</mark>](/ecosystem/the-graphite-explorer) and reinforced it with an API to empower developers with direct access to blockchain data via common GET/POST requests. Learn everything you need about blocks, transactions, fees and more.


# System Contracts

## About Graphite

At Graphite, we believe that reputation is the cornerstone of any highly functioning, healthy market. This is why we have built Graphite to be a reputation-based network. Graphite's architecture is designed to eliminate the waste of computational power that comes with PoW blockchains, gas betting, etc., but retains the ability to make an income for network participants without having to invest exorbitant amounts of resources.

All of this is achieved by implementing Graphite Key Features:

* Reputation-based smart contracts
* Efficient and effective KYC-Verification
* Transaction circle filters based on reputation (KYC, etc.)
* Efficient block validation (PoA consensus)
* Low and stable transaction costs
* Income for entry-point nodes.


# Account Activation

## Intro

<figure><img src="/files/7o2vQcyqEkpIpHvqYavl" alt="" width="563"><figcaption></figcaption></figure>

<mark style="color:green;">**`FeeContract.sol`**</mark> is a Graphite system smart contract. The contract is used to perform Account Activation. Without Account Activation, an account isn't able to send transactions to the blockchain.

* To activate your account and pay the fee for Account Activation, call <mark style="color:green;">**`pay()`**</mark>.
* <mark style="color:green;">**`changeFee(initialFee)`**</mark> is for administrative purposes and changes the fee for Account Activation.

### Network address of the contract

```
FeeContract_address = "0x0000000000000000000000000000000000001000"
```

## Functions

### pay()

* #### **Purpose**

Call <mark style="color:green;">**`pay()`**</mark> in order to pay the fee for Account Activation and activate the wallet address that called this function.

* #### **Arguments**

*none*

* #### **After Execution**

Upon successful execution of a function, the wallet address becomes activated.

If the currency value of a calling transaction is less than the <mark style="color:green;">**`InitialFee`**</mark>, the message Not enough Ether <mark style="color:green;">**`Provided.`**</mark> will be sent and account won't be activated.

* #### **Details**

An Activated Account is an account (wallet address) that is capable of sending outgoing transactions. Transactions from non-activated accounts are rejected by Graphite Nodes. *To determine if an account is activated, Graphite Nodes check if there are any transcations in the blockchain that originated from the account. Account Activation is always the first transaction of any user account on the network.*

The excessive value (fee) for account activation will be returned to the function caller.

### **changeFee(...)**

* #### **Purpose**

Determines the size of the fee for Account Activation. Only Graphite network admins (*owners of the FeeContract smart-contract*) can execute this function.


# Filter Contract (KYC Transaction Filters)

## Intro

<mark style="color:green;">**`FilterContract.sol`**</mark> is a Graphite system smart contract. It's needed for users to work with KYC-Filters for incoming transactions.

* To set a filter level for your account, call <mark style="color:green;">**`setFilterLevel(level)`**</mark>.
* To check the current KYC-Filter level of your account, call <mark style="color:green;">**`viewFilterLevel()`**</mark>.
* To check if a potential transaction from account A to account B goes through (i.e. isn't blocked by KYC-Filter on B), call <mark style="color:green;">**`filter(sender, destination)`**</mark>.

### Network address of the contract

```
FilterContract_address = "0x0000000000000000000000000000000000001002"
```

<figure><img src="/files/SKmwUWcvoN1hvwHl8303" alt="" width="563"><figcaption></figcaption></figure>

## Functions

### **setFilterLevel(level)**

```
    setFilterLevel(uint _level)
    ⎯⎯
    _level - uint; KYC-Filter for incoming transactions to be set.
```

* #### **Purpose**

Call <mark style="color:green;">**`setFilterLevel(level)`**</mark> to set up a value for a KYC transaction filter for incoming transactions, rejecting senders with KYC level lower than the filter value.

* #### **Arguments**

<mark style="color:green;">**`level`**</mark> - integer value; the value of the KYC Filter (*directly related to sender's KYC Level*)

* #### **After Execution**

Upon successful execution, a caller wallet address will have a KYC Filter for incoming transactions set at a certain value.

* #### **Details**

Since the exact number of available KYC Verification levels is not yet finalized, the level(value) of KYC Filters is not limited on the testnet. Additionally, at the moment there are no KYC Level restrictions that the KYC Center is able to grant. On the mainnet, it's expected that there'll be 2-5 available KYC levels.

Transactions that don't fit the KYC Filter are rejected by Graphite nodes.

### **viewFilterLevel()**

```
viewFilterLevel()
```

* #### **Purpose**

Call <mark style="color:green;">**`viewFilterLevel()`**</mark> to get the current KYC Filter level that a caller has for incoming transactions.

* #### **Arguments**

*none*

* #### **After Execution**

Function restores the KYC Filter level.

* #### **Details**

A wallet address can call this function only for itself, not for others.

### **filter(sender, destination)**

```
    filter(address _sender,address _destination)
    ⎯⎯
    _sender - address; wallet address of a sender in a potential transaction
    _destination - address; destination wallet address in this transaction
```

* #### **Purpose**

Call <mark style="color:green;">**`filter(sender, destination)`**</mark> to check if a transfer from sender address to destination address will or won't be rejected by the blockchain.

* #### **Arguments**

<mark style="color:green;">**`sender`**</mark> - wallet address of a sender of a potential transaction. destination - wallet address of the receiver (destination).

* #### **After Execution**

Returns <mark style="color:green;">**`true`**</mark> if sender's KYC level is greater than destination's KYC Filter level (i.e. a potential transaction will go through and won't be rejected by nodes).

Returns <mark style="color:green;">**`false`**</mark> if sender's KYC level is less than destination's KYC Filter level (i.e. a potential transaction won't go through and will be rejected by nodes).

* #### **Details**

This function uses the <mark style="color:green;">**`KYCContract`**</mark> smart contact to get KYC level data.


# KYC Contract

<figure><img src="/files/DdwGEh5ijXglH66b3R9j" alt="" width="563"><figcaption></figcaption></figure>

## Intro

<mark style="color:green;">**`KYCContract.sol`**</mark> is a Graphite system smart contract. It's needed for general users and KYC Centers to enable KYC Verification.

The KYC Verification process starts and finishes on the blockchain with function calls of this smart contract. But the KYC verification itself (information providing, verification of the authenticity) happens off-chain between a user and a KYC Center. All private data stays off-chain, only the result of the KYC verification is written on the blockchain.

<figure><img src="/files/CGaBpmCM9yb1p0Q4zsgT" alt="" width="563"><figcaption></figcaption></figure>

### **Primary actions**

* As a user, to apply for KYC Verification and transfer the deposit for KYC, call <mark style="color:green;">**`createKYCRequest(level, data)`**</mark>.
* As a KYC Center, to approve a user's KYC request and verify KYC Level, call <mark style="color:green;">**`approveKYCRequest(index)`**</mark>.
* As a KYC Center, to decline a user's KYC request in case of a failed verification, call <mark style="color:green;">**`declineRequest(index)`**</mark>.

### **Status of KYC**

* As a user, to view one of your KYC requests and check its status, call <mark style="color:green;">**`viewMyRequest(senderKYCIndex)`**</mark>.
* To get the global index of a user's last KYC request, call <mark style="color:green;">**`getLastGlobalRequestIndexOfAddress(addr)`**</mark>.
* To get a KYC request assigned to a KYC Center, call <mark style="color:green;">**`viewRequestAssignedToCentre(KYCCenteraddr, localKYCIndex)`**</mark>.

### **Corner-Cases**

* As a user, for a pending KYC Request in which the assigned KYC Center was revoked of its role, call <mark style="color:green;">**`repairLostRequest()`**</mark> to withdraw the KYC request and return the deposit.
* As a KYC Center, to revoke a user’s granted KYC Level (justification for the action required), call <mark style="color:green;">**`decreaseKYCLevel(addr, level)`**</mark>.

### **Misc**

* <mark style="color:green;">**`setLevelPrice(...)`**</mark> is for administrative purposes and changes the deposit size needed for each KYC Level.

### Network address of the contract

```
KYCContract_address = "0x0000000000000000000000000000000000001001"
```

## Functions

### **createKYCRequest(level, data)**

```
    createKYCRequest(uint _level, bytes32 _data)
    ⎯⎯
    _level - uint; desired KYC-Level (greater than current)
    _data - bytes32; has no use 
```

* #### **Purpose**

Call <mark style="color:green;">**`createKYCRequest(level, data)`**</mark> to request KYC Verification of a desired level for a caller account. *The requested KYC Level should be greater than the account's current KYC Level.*

A successful call starts the KYC Verification process which is carried out by a randomly selected KYC Center.

* #### **Arguments**

<mark style="color:green;">**`level`**</mark> - integer value; KYCLevel to be granted to a caller account upon successful KYC Verification.

<mark style="color:green;">**`data`**</mark> - 32 byte array; will be stored in KYCRequest object, has no meaningful use in current v. of Graphite.

* #### **After Execution**

Successful <mark style="color:green;">**`createKYCRequest()`**</mark> call creates <mark style="color:green;">**`KYCRequest`**</mark> object holding info (user addr, KYC Level, status, KYC Center, deposit) needed for KYC-Verification and stores it on the blockchain. Instances of<mark style="color:green;">**`KYCRequest`**</mark> have consecutive integer indexes starting from <mark style="color:green;">**`0`**</mark>. Pending <mark style="color:green;">**`KYCRequest`**</mark> has <mark style="color:green;">**`status`**</mark> equal to <mark style="color:green;">**`0`**</mark>.

This function appoints a randomly choosen KYC Center from the pool of compliant KYC Centers. The chosen KYC Center is the only one for this and related <mark style="color:green;">**`KYCRequest`**</mark>. Only this KYC Center has the power to then approve or decline the <mark style="color:green;">**`KYCRequest`**</mark>.

The verification itself is carried out off-chain by the appointed KYC Center. Upon completing it, the KYC Center calls <mark style="color:green;">**`approveKYCRequest(ind)`**</mark> or <mark style="color:green;">**`declineRequest(ind)`**</mark> functions of the KYCContract.sol (current one).

{% hint style="info" %}
*Note:* Only the result of KYC Verification is written on the blockchain. All private data stays off-chain between a user and a KYC Center which follows strict data protection and governance rules.
{% endhint %}

* #### **Details**

If a KYC Level of a function caller account is equal to or greater than the requested KYC level (<mark style="color:green;">**`level`**</mark> arg.), the error message <mark style="color:green;">**`You already have this KYC level`**</mark> will be sent and execution will be stopped.

If a caller has not finished KYCVerification, execution will be stopped with a <mark style="color:green;">**`Your previous request is still pending answer`**</mark> error-message. Approval or decline of an active <mark style="color:green;">**`KYCRequest`**</mark> is required for the creation of a new one.

If a currency fee bound to a calling transaction is less than the needed amount for the requested KYC Level, the message <mark style="color:green;">**`Provided not enough Ether.`**</mark> will be sent with no <mark style="color:green;">**`KYCRequest`**</mark> creation. The exceeding fee amount, if any, will be returned to the function caller.

The KYC Verification can only happen if there is at least one appointed KYC Center on the network. If there is none, <mark style="color:green;">**`There are no kyc centres`**</mark> error is thrown.

### **approveKYCRequest(index)**

```
    approveKYCRequest(uint _index) 
    ⎯⎯
    _index - uint; index of KYCReqeust to be approved
    
```

* #### **Purpose**

As the KYC-Center of a <mark style="color:green;">**`KYCRequest`**</mark>, call approveKYCRequest(ind) to approve the very <mark style="color:green;">**`KYCRequest`**</mark>.

* #### **Arguments**

<mark style="color:green;">**`index`**</mark> - integer value; Index of <mark style="color:green;">**`KYCRequest`**</mark> object to be approved.

* #### **After Execution**

Successful <mark style="color:green;">**`approveKYCRequest(index)`**</mark> call approves the <mark style="color:green;">**`KYCRequest`**</mark> under the <mark style="color:green;">**`index`**</mark> producing <mark style="color:green;">**`KYCLevelChanged(user, level)`**</mark>, <mark style="color:green;">**`RequestApproved(index)`**</mark> events.

Function changes the <mark style="color:green;">**`status`**</mark> of <mark style="color:green;">**`KYCRequest`**</mark> to <mark style="color:green;">**`2`**</mark>. Now the account in <mark style="color:green;">**`KYCRequest`**</mark> is officially granted the requested KYC-level.

In terms of payment, 50% of the <mark style="color:green;">**`KYCRequest`**</mark> deposit sum is sent to the user who created <mark style="color:green;">**`KYCRequest`**</mark>, the other 50% is sent to the KYC-Center responsible for approving <mark style="color:green;">**`KYCRequest`**</mark> (i.e. calling this function).

* #### **Details**

Execution will only go through if <mark style="color:green;">**`approveKYCRequest(index)`**</mark> is called by the KYC-Center mentioned <mark style="color:green;">**`KYCRequest`**</mark> under <mark style="color:green;">**`index`**</mark>.

Only KYC-Centers can call this function; <mark style="color:green;">**`Not allowed to approve`**</mark> error is thrown if called by a non-KYC-Center account.

If the <mark style="color:green;">**`KYCRequest`**</mark> isn't pending (<mark style="color:green;">**`status`**</mark> != 0), the <mark style="color:green;">**`This request is not pending decision`**</mark> error is thrown.

### **declineRequest(index)**

```
    declineRequest(uint _index) 
    ⎯⎯
    _index - uint; index of KYCReqeust to be declined
    
```

* #### **Purpose**

As the KYC-Center of a <mark style="color:green;">**`KYCRequest`**</mark>, call <mark style="color:green;">**`declineRequest(ind)`**</mark> to decline the very <mark style="color:green;">**`KYCRequest`**</mark>.

* #### **Arguments**

<mark style="color:green;">**`index`**</mark> - integer value; Index of <mark style="color:green;">**`KYCRequest`**</mark> object to be approved.

* #### **After Execution**

Successful <mark style="color:green;">**`declineRequest`**</mark> call declines the <mark style="color:green;">**`KYCRequest`**</mark> under the <mark style="color:green;">**`index`**</mark> producing a<mark style="color:green;">**`RequestApproved(index)`**</mark> event.

This unction changes the <mark style="color:green;">**`status`**</mark> of <mark style="color:green;">**`KYCRequest`**</mark> to <mark style="color:green;">**`1`**</mark>. The KYC-Level of the account in <mark style="color:green;">**`KYCRequest`**</mark> doesn't change.

In terms of payment, 50% of the <mark style="color:green;">**`KYCRequest`**</mark> deposit sum is sent to the KYC-Center which declined <mark style="color:green;">**`KYCRequest`**</mark> (i.e. called this function). The rest goes to the Graphite Foundation.

* #### **Details**

Execution will only go through if <mark style="color:green;">**`declineRequest(index)`**</mark> is called by the KYC-Center mentioned <mark style="color:green;">**`KYCRequest`**</mark> under <mark style="color:green;">**`index`**</mark>.

Only KYC-Centers can call this function; <mark style="color:green;">**`Not allowed to approve`**</mark> error is thrown if called by a non-KYC-Center account.

For security reasons, it's technically possible to call <mark style="color:green;">**`declineRequest(index)`**</mark> for both pending (<mark style="color:green;">**`status`**</mark> = 0) and approved (<mark style="color:green;">**`status`**</mark> = 2) instances of <mark style="color:green;">**`KYCRequest`**</mark>.

### **viewMyRequest(senderKYCIndex)**

```
    viewMyRequest(uint _senderKYCIndex)
    ⎯⎯
    senderKYCIndex - uint; account-specific index of KYCRequests of function caller 
    
```

* #### **Purpose**

An account calls <mark style="color:green;">**`viewMyRequest(senderKYCIndex)`**</mark> to get its <mark style="color:green;">**`KYCRequest`**</mark> object under an index (account-specific).

Then, for example, a user can check a <mark style="color:green;">**`status`**</mark> of <mark style="color:green;">**`KYCReuqest`**</mark>: Pending - <mark style="color:green;">**`0`**</mark>, Declined - <mark style="color:green;">**`1`**</mark>, Approved - <mark style="color:green;">**`2`**</mark>, Withdrawn due to loss of KYC-Center - <mark style="color:green;">**`3`**</mark>.

* #### **Arguments**

<mark style="color:green;">**`senderKYCIndex`**</mark> - integer value; Consecutive index (from <mark style="color:green;">**`0`**</mark>) of <mark style="color:green;">**`KYCRequest`**</mark> objects created by function caller account. This index is account-specific. It's not the same as the general index of<mark style="color:green;">**`KYCRequest`**</mark> objects mentioned elsewhere in this document.

* #### **After Execution**

Returns a caller account's <mark style="color:green;">**`KYCRequest`**</mark> under an account-specific index.

* #### **Details**

Calling with an invalid <mark style="color:green;">**`senderKYCIndex`**</mark> arg. (i.e. an account caller only successfully requested KYC twice; but <mark style="color:green;">**`viewMyRequest(4)`**</mark> is called) won't return <mark style="color:green;">**`KYCRequest`**</mark> object.

### **getLastGlobalRequestIndexOfAddress(addr)**

```
    getLastGlobalRequestIndexOfAddress(address _addr)
    ⎯⎯
    _addr - address; wallet address of a user
    
```

* #### **Purpose**

This function returns the index of the last <mark style="color:green;">**`KYCRequest`**</mark> created by the user under <mark style="color:green;">**`addr`**</mark>. Returns <mark style="color:green;">**`-1`**</mark> if there were none <mark style="color:green;">**`KYCRequests`**</mark> for the <mark style="color:green;">**`addr`**</mark>.

Anyone on the network can all this function.

### **viewRequestAssignedToCentre(KYCCenteraddr, localKYCIndex)**

```
    viewRequestAssignedToCentre(address _KYCCenteraddr, uint _localKYCIndex) 
    ⎯⎯
    _KYCCenteraddr - address; address of a KYC-Center
    _localKYCIndex - int; KYC-Center-specific index of assigned KYCRequest
```

* #### **Purpose**

Call <mark style="color:green;">**`viewRequestAssignedToCentre(KYCCenteraddr, localKYCIndex)`**</mark> to get <mark style="color:green;">**`KYCRequest`**</mark> object that was assigned to the KYC Center(<mark style="color:green;">**`KYCCenteraddr`**</mark>) under an index (KYC-Center-specific <mark style="color:green;">**`localKYCIndex`**</mark>).

### **decreaseKYCLevel(addr, level)**

```
    decreaseKYCLevel(address _addr, uint _level) 
    ⎯⎯
    _addr - address; wallet address of a user
    _level - int; desired KYC-Level (greater than current)
```

* #### **Purpose**

Function decreases the KYC Level of a specified account (<mark style="color:green;">**`addr`**</mark>) to a specified value (<mark style="color:green;">**`level`**</mark>). It can only be called by a KYC-Center.

The intended purpose of this function is to decrease an account's KYC Level due to fraudulent or suspicious activities. The calling of this function by KYC Centers follows strict guidelines. A KYC Center that abuses the usage of <mark style="color:green;">**`decreaseKYCLevel()`**</mark> will be removed from its role.

Only decreasing a KYC Level is possible with this mechanism for security reasons.

### **repairLostRequest()**

* #### **Purpose**

In an event that the KYC Center assigned to a pending KYCRequest is to be removed from their KYC Center role, <mark style="color:green;">**`KYCRequest`**</mark> cannot be resolved in a standard way.

In this case, the user (creator of <mark style="color:green;">**`KYCRequest`**</mark>) can call <mark style="color:green;">**`repairLostRequest()`**</mark>, to withdraw <mark style="color:green;">**`KYCRequest`**</mark> (sets its <mark style="color:green;">**`status`**</mark> = 3) and return all of the <mark style="color:green;">**`KYCRequest`**</mark> deposit.

### **setLevelPrice(...)**

* #### **Purpose**

Determines the fee size needed to start verification for a certain KYC Level. Only Graphite network admins (*owners of the KYCContract smart contract*) can call this function.


# Reputation

## Intro

<mark style="color:green;">**`Reputation.sol`**</mark> is a Graphite system smart contract. It's needed for users to create their own reputation-based smart contracts.

Reputation is calculated as follows:

$$
Reputation=CD+A+KYC+QTx+Diff
$$

<table><thead><tr><th width="212">Parameter</th><th>Сriteria</th><th>Reputation Score</th></tr></thead><tbody><tr><td>Creation date (CD)</td><td>more 100000 blocks ago</td><td>100</td></tr><tr><td></td><td>50000 - 100000 blocks ago</td><td>70</td></tr><tr><td></td><td>10000 - 50000 blocks ago</td><td>50</td></tr><tr><td></td><td>less 10000 blocks ago</td><td>0</td></tr></tbody></table>

<table><thead><tr><th width="211">Parameter</th><th width="329">Criteria</th><th>Reputation Score</th></tr></thead><tbody><tr><td>Activated (A)</td><td>Activated</td><td>100</td></tr><tr><td></td><td>Not Activated</td><td>0</td></tr></tbody></table>

<table><thead><tr><th width="211">Parameter</th><th width="330">Criteria</th><th>Reputation Score</th></tr></thead><tbody><tr><td>KYC</td><td>Level 0</td><td>0</td></tr><tr><td></td><td>Level 1</td><td>100</td></tr></tbody></table>

<table><thead><tr><th width="211">Parameter</th><th width="329">Criteria</th><th>Reputation Score</th></tr></thead><tbody><tr><td>Quantity of txn (QTx)</td><td>more 1000</td><td>100</td></tr><tr><td></td><td>500 - 1000</td><td>80</td></tr><tr><td></td><td>100 - 500</td><td>50</td></tr><tr><td></td><td>10 - 100</td><td>30</td></tr><tr><td></td><td>1 - 10</td><td>5</td></tr><tr><td></td><td>0</td><td>0</td></tr></tbody></table>

<table><thead><tr><th width="212">Parameter</th><th width="329">Criteria</th><th>Reputation Score</th></tr></thead><tbody><tr><td>Difference (Diff)</td><td>(all in - all in) more 0.1 @G</td><td>50</td></tr><tr><td></td><td>(all in - all out) less 0.1 @G</td><td>0</td></tr></tbody></table>

### Network address of the contract

```
Reputation_address = "0x0000000000000000000000000000000000001008"
```

## Functions

### getReputation(address addr)

* **Purpose**

Call <mark style="color:green;">**`getReputation(address addr)`**</mark> to get the reputation of a particular address.

* **Arguments**

<mark style="color:green;">**`address`**</mark> -  wallet address.

* **After Execution**

This function returns the reputation.&#x20;


# How to Complete KYC in a Testnet

We’ve implemented a simple KYC emulation process for testnet environments. Just send a UUID, and you’ll receive either <mark style="color:green;">**`approval or rejection with a 50% probability`**</mark>.<br>

Before using the API, you must first submit a KYC request to the contract.\
See the documentation [<mark style="color:green;">here</mark>](https://docs.atgraphite.com/build-on-graphite/system-contracts/kyc-contract).

Call the method **`createKYCRequest(uint _level, bytes32 _data)`**\
Use **`sha256(uuid)`** as the **`_data`** parameter.

This API is designed to simplify the process of emulating KYC in a testnet environment, allowing developers to efficiently test workflows that depend on KYC outcomes.

> The 50% approval/rejection mechanism is designed for test purposes only. No actual KYC verification is performed.

#### Endpoint:

**`POST https://test.kyc.atgraphite.com/api/kyc/process-request`**

#### Request:&#x20;

```javascript
{
  "data": "uuid"
}
```

Test your KYC workflows easily with this tool.


# How to Deploy Smart Contracts Using Hardhat: A Step-by-Step Guide

This guide will walk you through deploying a smart contract using Hardhat.

## Prerequisites

Before we begin, make sure you have the following:

1. Node.js installed (version 12.0.0 or later).
2. NPM or Yarn.
3. [<mark style="color:green;">**`Activated Graphite account`**</mark>](/overview/graphite-account-activation).
4. Basic knowledge of Solidity and smart contracts.

### Step 1: Install Node.js and NPM (if not already installed)

Download Node.js from the official site and follow the instructions for installation. This will also install NPM (Node Package Manager), which is needed to install Hardhat and other dependencies.

### Step 2: Create a New Hardhat Project

Open a terminal and create a new directory for your project, then navigate:

```javascript
mkdir my-project
cd my-project
```

Initialize an empty project and install Hardhat:

```javascript
npm init -y
npm install --save-dev hardhat
```

Once the installation is complete, run Hardhat to initialize your project:

```javascript
npx hardhat
```

Hardhat will present a menu of options. Select <mark style="color:green;">**`Create an empty hardhat.config.js`**</mark> for simplicity.

### Step 3: Install Additional Dependencies

You’ll need to install a few additional libraries that will help with writing and deploying contracts:

```
npm install --save-dev @nomiclabs/hardhat-ethers ethers
npm install dotenv
```

<mark style="color:green;">**`ethers.js`**</mark> helps interact with the Ethereum blockchain.

<mark style="color:green;">**`dotenv`**</mark> allows you to store environment variables securely (e.g., private keys).

### Step 4: Write Your Smart Contract

Create a folder named <mark style="color:green;">**`contracts`**</mark> in the root of your project:

```
mkdir contracts
```

Inside the <mark style="color:green;">**`contracts`**</mark> folder, create a new Solidity file, <mark style="color:green;">**`MyContract.sol`**</mark>. Below is a simple example of an ERC20 token contract:

```javascript
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
    constructor() ERC20("MyToken", "MTK") {
        _mint(msg.sender, 1000 * 10 ** 18);
    }
}
```

This contract creates an ERC20 token named "MyToken" with the symbol "MTK" and an initial supply of 1000 tokens.

### Step 5: Configure Hardhat for Deployment

In the root of your project, locate or create the <mark style="color:green;">**`hardhat.config.js`**</mark> file. Configure it to deploy to a specific network. Add the following configuration:

```javascript
require('@nomiclabs/hardhat-ethers');
require('dotenv').config();
module.exports = {
  solidity: "0.8.0",
  networks: {
    graphite: {
      url: process.env.RPC_URL,
      accounts: [process.env.PRIVATE_KEY]
    },
  },
};
```

* <mark style="color:green;">**`PRIVATE_KEY`**</mark> is your wallet private key. <mark style="color:green;">**`Do not expose it publicly`**</mark>.

To securely store your API keys, create a <mark style="color:green;">**`.env file`**</mark> in the root of your project:

```javascript
RPC_URL="https://anon-entrypoint-1.atgraphite.com"
PRIVATE_KEY="your-private-key-here"
```

### Step 6: Write a Deployment Script

Create a folder named <mark style="color:green;">**`scripts`**</mark> and inside it, create a <mark style="color:green;">**`deploy.js`**</mark> script:

```
mkdir scripts
```

In <mark style="color:green;">**`scripts/deploy.js`**</mark>, add the following code:

```javascript
async function main() {
    const [deployer] = await ethers.getSigners();
    console.log("Deploying contracts with the account:", deployer.address);
 
    const balance = await deployer.getBalance();
    console.log("Account balance:", balance.toString());
 
    const Token = await ethers.getContractFactory("MyToken");
    const token = await Token.deploy();
 
    console.log("Token deployed to:", token.address);
  }
 
  main()
    .then(() => process.exit(0))
    .catch(error => {
      console.error(error);
      process.exit(1);
    });
```

### Step 7: Compile the Contract

Before deploying, compile your Solidity contract:

```
npx hardhat compile
```

If everything is set up correctly, this should compile without errors.

### Step 8: Deploy the Contract <a href="#step-8-deploy-the-contract" id="step-8-deploy-the-contract"></a>

Run the deployment script:

```
npx hardhat run scripts/deploy.js --network graphite
```

This command will deploy your contract to the Graphite network using the configuration provided in <mark style="color:green;">**`hardhat.config.js`**</mark>.

### Step 9: Verify the Deployment <a href="#step-9-verify-the-deployment" id="step-9-verify-the-deployment"></a>

Once the deployment is successful, Hardhat will print the contract address in the terminal. You can verify the contract on a [<mark style="color:green;">**Graphite Explorer**</mark>](/ecosystem/the-graphite-explorer) by searching for the deployed contract address.

### Step 10: Interact with the Contract <a href="#step-10-interact-with-the-contract" id="step-10-interact-with-the-contract"></a>

After deployment, you can interact with your contract using <mark style="color:green;">**`ethers.js`**</mark>. Here's an example of how to call a function on your contract:

1. Create a new script called <mark style="color:green;">**`interact.js`**</mark> in the <mark style="color:green;">**`scripts`**</mark> folder.&#x20;

```javascript
async function main() {
    const Token = await ethers.getContractFactory("MyToken");
    const token = await Token.attach("your-deployed-contract-address-here");
 
    const totalSupply = await token.totalSupply();
    console.log("Total Supply:", totalSupply.toString());
 
    const name = await token.name();
    console.log("Token Name:", name);
  }
 
  main()
    .then(() => process.exit(0))
    .catch(error => {
      console.error(error);
      process.exit(1);
    });
```

2. Run the script to interact with the contract:

```
npx hardhat run scripts/interact.js --network graphite
```


# SDK


# JS SDK

A plugin for working with the Graphite transactions.

### Installation

```javascript
npm install @atgraphite/web3-plugin
# or
yarn add @atgraphite/web3-plugin
```

### Getting Started

To use this plugin simply import it, and add register it to your web3 instance.

```javascript
import { GraphitePlugin } from "@atgraphite/web3-plugin";

const NODE_URL = 'node url';
const web3 = new Web3(NODE_URL)
web3.eth.accounts.wallet.add(privateKey)
web3.registerPlugin(new GraphitePlugin(web3))
```

You can use our nodes instead of **`node_url`**. They are available [<mark style="color:green;">here</mark>](https://docs.atgraphite.com/overview/publish-your-docs).\
\
And you're ready to go!  There are 2 types of nodes, normal and anonymous. Read more about them [<mark style="color:green;">here</mark>](https://docs.atgraphite.com/).

### First time users

After registering the plugin, you need to activate you account:

```javascript
await web3.graphite.activateAccount()
```

which has a fee, more about that [<mark style="color:green;">here</mark>](https://docs.atgraphite.com/build-on-graphite/system-contracts/account-activation).&#x20;

To check the fee amount, use:

```javascript
await web3.graphite.getActivationFeeAmount()
```

### Interface

The following functions are accessible via web3.graphite.(\*)

```javascript
async getActivationFeeAmount()
async activateAccount()
async isActivated(address: string = this.getWalletAddress())
async getFilterLevel()
async setFilterLevel(newLevel: number)
async createKYCRequest(uuid: string, newLevel: number)
async getKycLevel(address: string = this.getWalletAddress())
async getLastKycRequest()
async repairLostKycRequest()
async cancelKycRequest()
async getKYCFee(level: number)
async sendTransaction(txData: TxData)
async patchFields(txData: TxData)
async getReputation(address: string = this.getWalletAddress())
getWalletAddress()
getWalletPrivateKey()
getWallet()
async getEpAddress()
```


# GraphiteTx (Type 100)

### What is it?

<mark style="color:green;">**GraphiteTx (type 100)**</mark> is a transaction format used in the Graphite network.\
It was introduced to support the <mark style="color:green;">**Entry-Point node address**</mark> (<mark style="color:green;">**`epAddress`**</mark>), which identifies the node through which a transaction enters the network.

Thanks to this mechanism, nodes can <mark style="color:green;">**legitimately earn a portion of transaction fees**</mark> by acting as entry points for user transactions.

### Key Features of GraphiteTx (Type 100)

| Field        | Description                                                   |
| ------------ | ------------------------------------------------------------- |
| `epAddress`  | Address of the Entry-Point node that accepted the transaction |
| `type: 0x64` | Indicates this is a new Graphite transaction                  |
| `accessList` | Access list support, similar to EIP-2930                      |
| Signature    | Same as AccessListTx format                                   |

{% hint style="warning" %}
The **`epAddress`** field is optional.\
\
If it is omitted, the transaction is treated as **anonymous**, and the Entry-Point node will **not receive any reward**.
{% endhint %}

You can create and send GraphiteTx (type 100) transactions using our official [<mark style="color:green;">**SDK**</mark>](/build-on-graphite/sdk).

### Technical Details

**Type:** `0x64`&#x20;

#### Example structure:

```
[
  chainId, 
  nonce, 
  gasPrice, 
  gasLimit,
  to, 
  value, 
  data,        
  accessList,
  epAddress,
  v, r, s
]
```

### How does this relate to Entry-Point node income?

Transactions of type 100 enable the following:

* Include the address of the node through which the transaction entered the network (<mark style="color:green;">**`epAddress`**</mark>)
* Allow the network to <mark style="color:green;">**share transaction fees**</mark> with that Entry-Point node

In short, <mark style="color:green;">**GraphiteTx (type 100) makes it possible to earn through infrastructure**</mark>, not through mining or staking.

### RPC Method: `graphite_getEpAddress`

The <mark style="color:green;">**`graphite_getEpAddress`**</mark> RPC method allows you to <mark style="color:green;">**check if a specific Graphite (Entry-Point) node has a registered blockchain address**</mark>, and if so, what it is.

This address is used to receive rewards for handling incoming <mark style="color:green;">**GraphiteTx (type 100)**</mark> transactions that specify an <mark style="color:green;">**`epAddress`**</mark>.

**Why is this useful?**

* The public Entry-Point address acts as the <mark style="color:green;">**identifier**</mark> of a node eligible to receive a portion of transaction fees.
* If a node is anonymous (by choice or config), this method will return `null` or an error.
* This is helpful when you want to:
  * Confirm that you're using a node with an active `epAddress` (i.e. one that can earn rewards)
  * Check your own node's identity
  * Configure infrastructure (e.g. wallet or service backend) to target a specific earning node

&#x20;**Example Request :**

```bash
curl --data '{
  "method":"graphite_getEpAddress",
  "params":[],
  "id":1,
  "jsonrpc":"2.0"
}' \
-H "Content-Type: application/json" \
-X POST https://entrypoint-test-1.atgraphite.com
```

#### Example Response:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0xb95BB87CC1CEE567185ECf61E0C1B5DF19a6e120"
}
```


# Public UI-Kit

**Graphite interface design requirements**:  [<mark style="color:green;">**UI-kit in Figma**</mark>](https://www.figma.com/design/jeovN6z2XhRVvcHDMsFBYK/Graphite-ui-kit?node-id=196-2658\&t=MBFRDI8Cow8GvTly-1)

## Layout and style

### **Layout**

In Graphite we use classic layout with header and footer. Content can be structured in any way within the grid framework.&#x20;

### **Main breakpoints**

**Desktop**: 1400 px – 1200 px

**Tablet**: 1200 px – 768 px

**Mobile**: 768 px – 360 px

### **Grid**

<table data-header-hidden><thead><tr><th></th><th></th><th></th><th></th><th></th><th data-hidden></th></tr></thead><tbody><tr><td><strong>Columns</strong></td><td><strong>Gutter</strong></td><td><strong>Side margins</strong></td><td><strong>Top/bottom margins</strong></td><td><strong>Content weight</strong></td><td><strong>Device</strong></td></tr><tr><td>12</td><td>24px</td><td>80px</td><td>64px</td><td>1200px (max)</td><td>Desktop</td></tr><tr><td>8</td><td>24px</td><td>24px</td><td>64px</td><td>full (max 1152px)</td><td>Tablet</td></tr><tr><td>4</td><td>16px</td><td>16px</td><td>48px</td><td>full (max 736px)</td><td>Mobile</td></tr></tbody></table>

### **Corner radius**

Blocks in the interface, controls, and highlighted areas use border radius as follows:

* **Labels**: <mark style="color:green;">**2px**</mark> — for small ui-elements
* **Inputs**: <mark style="color:green;">**4px**</mark> — main radius for elements 48 pixels and smaller
* **Small blocks and controls**: <mark style="color:green;">**8px**</mark> — a universal radius for most UI elements.
* **Large blocks and pop-ups**: <mark style="color:green;">**16px**</mark> — used for modals and maintains a balanced proportion between element size and rounding.

### **Module**

The 8-pixel module is the basic dimensional unit of Graphite interfaces. The module is used to build typography and controls, select sizes for icons, and calculate indents between elements.

For sizes up to 40 px, a half-module step is acceptable: 0.5 module = 4 px, for sizes smaller than 24 px — 0.25 module = 2 px.

> *We use the module wherever it doesn't compromise aesthetics or common sense. The module is a practical design guide — it helps define sizes and spacing, but it’s not an absolute rule. Layouts don’t need to rigidly follow the 8-pixel grid.*

## Colors and typography

### **Colors and mode**

Graphite uses dark mode exclusively. Main interface colors are black and gray, white for text, green — accent. The background should always be darker than other elements. If you use a modal container or backdrop layer, the inputs and other filled elements should be lighter than the background of the modal window.

### **Text styles**

#### **headline-large**

This style is intended for use <mark style="color:green;">**only in the first block of a webpage on desktop**</mark>, typically when:

* the section contains <mark style="color:green;">**only text**</mark> (no images, cards, or complex layout),
* the heading is <mark style="color:green;">**short**</mark> — no more than 1–2 lines,\
  there are <mark style="color:green;">**no other dominant elements**</mark> competing for attention,
* the goal is to create a <mark style="color:green;">**strong, spacious, and minimal first impression**</mark>.

It works best in <mark style="color:green;">**hero sections**</mark> where typography is the focal point — for example, hero headlines. Avoid using this heading style in sections with multiple visual components or dense content — it may appear oversized or out of balance.

#### **headline-medium**

The main header for the desktop and can be used for tablet.

#### **headline-small**

The main header for the mobile also can be used for tablet.

#### **body-large**

This text style is used to create a <mark style="color:green;">**strong typographic hierarchy**</mark> and guide the reader’s attention. It serves two main purposes:

* **Introductory paragraph in articles or long-form content**\
  Used as a <mark style="color:green;">**lead paragraph**</mark> to set the tone and provide context before the main body text. It should be concise, readable, and visually distinct from regular paragraphs.
* **Subheading beneath a headline-large**\
  When paired with a headline-large, this text functions as a **supportive subtitle** — offering additional context or clarifying the message without competing in visual weight.

#### **body-big**

Basic text for descriptions inside cards, modal windows and pop-ups, can be used on all resolutions.

#### **body-medium**

Used for texts inside elements — toggles, inputs for small resolutions, texts in tooltips, in pairs with radio buttons.

#### **body-small**

Used for text labels.

#### **button-big and button-small**&#x20;

Used for buttons according to size.

## Icons

Graphite interfaces use material design icons with rounded corners with outlining and without filling.&#x20;

There are four main icon sizes — 12px, 16px, 20px, 24px. Icons could be scaled to other sizes inscribed in the module system.

## Buttons and links

The name of the button is capitalized. The name of the button should be clear and concise, fitting completely within the button boundaries. Do not abbreviate button labels unless the full meaning is immediately clear.

There are 2 standard button sizes — big and small.&#x20;

* **Small** — when the button is next to small input fields or other types of buttons.
* **Big** — use as main screen or form buttons to save and cancel, move to the next screen.

### **Text buttons**

There are 3 types of text buttons — primary, secondary and plane.&#x20;

* **Primary button** — represents the <mark style="color:green;">**main action**</mark> on a screen, section, or component. It draws the most attention and guides the user toward the intended outcome.&#x20;

> **Primary scenarios**: main CTA on the page or section, highlighting the next step in a flow, single action within a component, destructive confirmation (with visual caution).

* **Secondary button** — used for non-primary actions: actions that are important but not the main focus of the current screen or block.&#x20;

> **Primary scenarios**: in a pair with a primary CTA, as a standalone action in low-attention areas, for repeated/utility actions, inside components with visual hierarchy.&#x20;

* **Plain button** — a low-emphasis, minimal button style. It visually resembles a text link, but functions as a button for actions, not navigation.

> **Primary scenarios**: lightweight or secondary actions within components, inline actions within copy or content, supplementary actions in forms or modals.

The name of the button can be complemented with an icon. It helps find the desired button faster and understand its function at a glance. For buttons with an icon apply the same rules as for buttons without an icon.

### **Icon buttons**

Icon buttons are compact, visual-only buttons used for clear, self-explanatory actions. They contain only an icon, without a label, and are designed for high-recognition, low-ambiguity actions. <mark style="color:green;">**Only use icon-only buttons for well-known actions — don’t assume users will guess less common ones.**</mark>

> **Primary use cases**: essential utility actions (search, copy, close), compact placement in tight UI (edit, delete, clear input).

### **Input Buttons**

Input buttons are small action buttons placed next to input fields, usually inside or beside number or token inputs. They help users quickly insert a contextual value.

> **Common use cases**: set max/min value, quick actions like “Paste”, “Clear”.

### **Links**

Links are used to navigate between pages, sections, or external resources. Different link styles help distinguish their purpose and importance. There are 4 types of links — external link, inner primary link, inner secondary link and socials.&#x20;

* **External link** — used for links that lead outside the product or ecosystem. Opens in a new browser tab, accompanied by an external link icon.
* **Inner primary link** — used for important internal links within the product or ecosystem. May lead to key pages, styled with accent color to stand out, can be used inline or as part of navigation elements.
* **Inner secondary link** — used for less prominent internal links — still important, but not part of the main flow. Often used in footers, legal blocks, or secondary content, styled more subtly (neutral or gray tones).
* **Social link** — an icon-based link that directs to a company’s social media profile. Opens in a new tab, uses in personal accounts.&#x20;

> ***Note**: Social links are used to direct users to the company’s official social media profiles. They are styled and behave like secondary icon buttons, not like social links.*

### **Checkboxes**

Use checkboxes for:

* Selecting items from a list. For example, choosing multiple documents for bulk actions.
* Selecting options or preferences. For example, enabling notifications and choosing specific cases when notifications should be sent.

Checkboxes do not trigger an action immediately. Typically, the user needs to press a separate confirmation button to apply the change. If an action needs to happen instantly, a toggle is a better choice.

The checkbox is vertically aligned with the center of the first line of the text it belongs to. If the text spans multiple lines, the checkbox is aligned to the top edge of the text container.

### **Radio buttons**

Use a radio button group when there are only a few options — typically 2 to 5. Radio buttons are vertically aligned with the center of the text line.

> ***Note**: if there are 5 to 25 options, a dropdown is more appropriate.*

## Tabs and toggles

### **Tabs**

Tabs are used for secondary navigation, and for grouping or filtering content.

Do not use tabs to switch between states — use radio buttons, toggles, or switches instead.

There are 3 types of tabs — tab with background and icon, text tab with background, plain text tab.<br>

When to use each type:

Tabs with background are used to switch between sections of content within a page — for example, multiple tables or data views. They should not be used inside other components (like modals). In those cases, use plain text tabs instead.<br>

* **Tab with background and icon** — used when there are only a few tabs (up to 5). The icon helps reinforce the meaning of the text but adds visual noise, so it’s not recommended for large sets.
* **Text tab with background** — no icon is preferred when there are more than 5 tabs, to maintain a cleaner and more readable layout.
* **Plain text tab** — used when tabs appear inside another component, such as a modal window. These tabs can also be placed outside the visual bounds of the component they control.

#### Best practice

Tab styles are flexible — choose the version that fits your layout best while maintaining usability and clarity. Tabs should be easy to use and understand, but should not create unnecessary visual noise.

### **Toggles**

A toggle is used to switch between two states, such as changing the payment currency or switching a content view. Functionally, a toggle is similar to a checkbox, but the context of use is different: toggles are larger and more visually prominent than checkboxes. Ideally, a page should contain no more than 1–2 toggles, with 3 as a maximum.

There are two types of toggles:

**Big toggle** — used when the label is longer — typically 1–3 words, can be placed as a standalone UI element, works well in settings panels or feature switches.

**Small toggle** — used when the label is short such as an abbreviation or icon, best suited for compact interfaces like modals or dropdowns.

Toggles are best used when both states are clearly understood by the user (e.g., On/Off, USD/EUR). The change takes effect immediately. If confirmation is required, use a checkbox and button instead.

## Inputs

There are 2 main types of input fields — standard input fields and search fields with advanced behavior.

### **Standard Input Field**

Used in forms and feedback blocks to collect user data such as email, wallet address, phone number, etc.

Primary use cases:&#x20;

* can be used with or without a label, but always includes a placeholder
* always includes a clear icon (a cross) to reset the field
* supports various input types: text, email, number, etc.
* used in contact forms, wallet connections, account creation, etc.

### **Search Field**

Used as a standalone UI element, not typically placed inside other components like pop-ups or forms.

Primary use cases:&#x20;

* taller than a standard input field (on desktop)
* may include a dropdown state — recent search history, autocomplete suggestions, country/region code selectors
* can be full-width inside content container for better usability
* designed for dynamic interaction, not static form submission

Use search fields when the user expects real-time feedback and standard input fields for structured data collection with or without submission confirmation.

> ***Note:** when an input field is placed next to a button, it's important that they are the same height to ensure visual consistency and alignment.*

## Dropdowns

The element that opens a dropdown list visually resembles a button, but behaves differently — does not trigger an action immediately, is used alongside other input fields. This component is best used when the user needs to choose one option from a list, especially in form-like contexts.

Dropdown panel behavior

* The dropdown panel is aligned to the right edge of the trigger button, but may stretch to full width if needed.
* The panel has a shadow to separate it from the background.
* Items inside the dropdown are left-aligned.
* The selected item is highlighted with a gray background.
* Items can include labels and icons to provide additional context.

## Labels

Text labels are small UI elements used to indicate status, type, or category of an object. They are compact, text-based, and serve a semantic and visual tagging function.

Purpose and usage

* Indicate the status of a process or item (e.g., “Pending”, “Success”, “Failed”)
* Show type or category (“Wallet”, “Beta”, “Layer 2”)
* Can be used in lists, cards, tables, or inline with content

Visual style — use the smallest text size available (e.g., body-small). Labels include a background fill and 2px rounded corners.

\
**Label types**

* **Neutral (gray) labels** — used for generic tags
* **Colored status labels** — reflect specific states in a process

Labels should be short and readable, usually 1–2 words, and never behave like interactive elements.&#x20;

## Tooltips

A tooltip is a small informational element that provides contextual help or explains the state of a control.

**Behavior**

* Appears on hover over an interface element
* Should remain visible when the cursor moves from the target to the tooltip itself
* Should disappear only when the cursor leaves both the target and the tooltip

**Size & Placement**

* The tooltip can appear in any direction, depending on available space and layout
* There must be a 4px gap between the tooltip and the element that triggered it
* The tooltip should not span the full width of the screen, the maximum width of a tooltip is 280px

**Content**

* Use body-medium or body-small text styles inside the tooltip, depending on content length and importance, keep the message concise, informative, and easy to scan.
* The text inside a tooltip should always be left-aligned, regardless of the tooltip’s position on screen.

Tooltips should help users understand interface elements without overwhelming them. Use them only when necessary and never for critical information.

## Notifications

To notify users, you can use either a toast or a modal window, depending on the context.

**Toasts** are used for brief, non-intrusive messages — such as status updates or confirmations. They appear in the top-right corner of the screen. Toasts can contain a short message and and may include a link or action button if needed.

**Behavior**

* A toast with short text only automatically disappears after 5 seconds
* If the toast includes a link, button, or a loading indicator, it remains visible until the user dismisses it

**Modals** are used for secondary content that’s only relevant in certain situations or when you need to focus the user's attention on a specific action.\
\
**Behavior**

* Appears on top of the current page
* The background is dimmed to reduce distraction
* The user must interact with the modal before continuing

## Keyboard Navigation & Focus State

Focus state indicates that an element is active and can be interacted with using the keyboard. It is essential for accessibility and keyboard navigation.

### **Focus Outline**

* The focus state is shown as a 1px outline in the appropriate color
* The corner radius of the focus outline matches the element’s existing border radius
* If the element has no border radius (e.g. a plain text container), a default 8px radius is applied
* If the element already has a border, the focus outline appears on top of it

### **Focus Outline Colors by Element Type**

**Green 900**

Default focus color. Used for:

* Input fields
* Dropdowns and list items
* Secondary icon buttons
* Input clear buttons and copy buttons
* Tabs and toggles
* Any element with a gray background or no background

**White 500**

Used when the element has a green background. Applied to:

* CTA buttons (green 500 background)
* Clickable green icons
* Links on dark backgrounds<br>

**Green 500**

Used for:

* Secondary buttons
* Plain buttons


# Graphite Nodes

{% hint style="success" %}
If you are interested in becoming a validator, please contact us at <mark style="color:green;">**<support@atgraphite.com>**</mark>.
{% endhint %}

Graphite has three key types of nodes on its network:&#x20;

* Entry-point (Transport) Nodes
* Authorized Nodes
* Graphite Foundation Nodes

Each type helps to ensure high network performance and practical usability.

## Transport Nodes Income

Usually, standard transport nodes do not earn incomes on blockchains. So, one of Graphite’s key unique features is that it actually allows its regular entry-point transport nodes to earn an income. Put simply, it is easy to create a transport node and start earning by allowing Graphite users to send transactions to the network from your node.

Income for Entry-Point Nodes; How It Works Step-by-Step:

* The transaction sender includes the ‘originating node’ address in the data field of the transaction
* The transaction is not accepted by the entry-point node if the ‘originating node’ differs from the actual node's address
* After the block containing the transaction is sealed, the entry-point node is rewarded with 50% of the transaction fee (i.e. the fee). The other 50% goes to the authorized node serving as a block sealer.

## Income for Entry-Point Nodes

> Entry-point nodes in Graphite are transport nodes that also act as initial points of transaction entry to the network. Unlike any other blockchain, Graphite allows its entry-point nodes to earn an income from part of the transaction fee. This feature of the network makes it possible for users to start making an income as an entry-point node without the need for huge server resources.

The income for transport nodes in Graphite is technically achieved by adding a field for the incoming node address to a transaction record. When a user fills this field with a valid "originating node" address, the transaction fee will be the standard rate (i.e. the lowest possible fee). On the other hand, the fee for anonymous transactions (i.e. without a complete ‘originating node’ address) will be increased; but, to be clear, we do not in any way prohibit anonymous transactions.

<figure><img src="/files/ho0VozbymNOpmh9klZgQ" alt="" width="563"><figcaption></figcaption></figure>

The "originating node" address is necessary for a transport node to receive its reward for the initial admission (i.e. point of entry) of a transaction to the Graphite network. The address of the "originating node" essentially serves as an identifier for the node set to receive the income. Of course, this system inevitably decreases anonymity since everybody on the network will see a particular node related to a specific transaction. But, realistically, most users have no interest in these matters and simply choose the node (i.e. wallet provider) that is the closest and provides the best services.

<figure><img src="/files/urtkP5qFl8CD5g8RDKdx" alt="" width="563"><figcaption></figcaption></figure>

{% hint style="info" %}
For users who value anonymity and privacy, it will be possible to create a Graphite transport node and use it to send transactions with no "originating node" data; again, Graphite doesn’t make them reveal which node was used as an entry point for a transaction if the user does not wish to reveal it.

In other words, in order to earn money, Graphite network participants should focus on providing great performance and user experience by acting as an entry-point node for other user transactions instead of simply performing pointless and wasteful calculations. We believe this is the best way forward for any blockchain transaction system.
{% endhint %}

## Authorized Nodes

> Authorized nodes on the Graphite network are responsible for the validation of new blocks. The pool of authorized nodes consists of compliant, authorized nodes and Graphite Foundation nodes which are always available.

Graphite-authorized nodes are the primary core of the network and act as block validators. For a server to become a compliant, authorized node on the Graphite network, it must pass a compliance test.

The compliance test for authorized nodes will be described in detail in a dedicated document. For now, we will note that the compliance process involves:

* Passing the highest level KYC verification
* Technical requirements, including:
  * SLA for 99.9% server uptime;
  * A server hosted in a Tier 3 or Tier 4 data center or higher;
  * High server speed and performance;
  * 2TB SDD.

After becoming a legitimate authorized node, the node will be able to validate blocks and earn income.

Graphite will take note of its nodes with the best and worst performances and implement a mechanism to reward authorized nodes for good performance.

## Graphite Foundation Nodes

> Graphite Foundation nodes are meant to ensure that the Graphite network is live and functioning in any situation (even when all other nodes are down). 16(incl. 7 validators) high-level Graphite Foundation nodes, managed and maintained by the Graphite Foundation, will support the uptime of the Graphite network.


# Graphite testnet node setup

### Requirements

Make sure you have the latest docker installed.\
Make sure you have opened and not binded with other applications 8575/tcp, 30311/udp ports in order to communicated with node via rpc endpoint(8575) and also node can communicate with other nodes in network via p2p(30311). Websocket modules avialable at 8576 port. Also make sure you dont covered by nat or any other network stuff.

In order to run localy with docker you need to create folder for persist data inside container.&#x20;

```bash
mkdir graphite-data

chown 10001:10001 graphite-data
```

\
After creating folder you need to run init task to inject genesis and persist it. You can do it with following command:

{% code overflow="wrap" %}

```bash
docker run -it -v ./graphite-data:/home/geth/data ghcr.io/atgraphite/graphite:v1.3.3-testnet /bin/sh init-genesis.sh
```

{% endcode %}

### Anonymous entrypoint node setup instructions

Now you can run your node. In order to do it use following command:

{% code overflow="wrap" %}

```javascript
docker run -d --name graphite-testnet --network host -v ./graphite-data:/home/geth/data ghcr.io/atgraphite/graphite:v1.3.3-testnet geth --datadir /home/geth/data --config /home/geth/config.toml
```

{% endcode %}

### Keyed entrypoint node setup instructions

Prepare your public key for inject into entrypoint with flag --epaddr. In example we will be using 0x8D1Ee942A92645136c81271460fD7Ec5375B30cC address. Now you can run your node. In order to do it use following command:

{% code overflow="wrap" %}

```javascript
docker run -d --name graphite-testnet --network host -v ./graphite-data:/home/geth/data ghcr.io/atgraphite/graphite:v1.3.3-testnet geth --datadir /home/geth/data --config /home/geth/config.toml --epaddr 0x8D1Ee942A92645136c81271460fD7Ec5375B30cC
```

{% endcode %}

Node rpc api is avaialable at <mark style="color:green;">**`http://127.0.0.1:8575`**</mark>

### **Usefull commands**

You can check node sync proggress with following command. If sync is done you will sync done message if not you will see elapsed blocks:

{% code overflow="wrap" %}

```javascript
docker exec -it graphite-testnet geth --exec 'eth.syncing.currentBlock == eth.syncing.highestBlock ? console.log("sync done") : console.log("sync in progress. elapse blocks: ", eth.syncing.highestBlock - eth.syncing.currentBlock);' attach /home/geth/data/geth.ipc
```

{% endcode %}

To attach node logs:

```bash
docker logs graphite-testnet --follow
```

To interact node with graphite js console use following command:

```bash
docker exec -it graphite-testnet geth attach /home/geth/data/geth.ipc
```


# Graphite mainnet node setup

### Requirements

Make sure you have the latest docker installed.\
Make sure you have opened and not binded with other applications 8575/tcp, 30311/udp ports in order to communicated with node via rpc endpoint(8575) and also node can communicate with other nodes in network via p2p(30311). Websocket modules avialable at 8576 port. Also make sure you dont covered by nat or any other network stuff.

In order to run localy with docker you need to create folder for persist data inside container.&#x20;

```bash
mkdir graphite-data

chown 10001:10001 graphite-data
```

\
After creating folder you need to run init task to inject genesis and persist it. You can do it with following command:

{% code overflow="wrap" %}

```bash
docker run -it -v ./graphite-data:/home/geth/data ghcr.io/atgraphite/graphite:v1.3.3 /bin/sh init-genesis.sh
```

{% endcode %}

### Anonymous entrypoint node setup instructions

Now you can run your node. In order to do it use following command:

{% code overflow="wrap" %}

```bash
docker run -d --name graphite-mainnet --network host -v ./graphite-data:/home/geth/data ghcr.io/atgraphite/graphite:v1.3.3 geth --datadir /home/geth/data --config /home/geth/config.toml
```

{% endcode %}

### Keyed entrypoint node setup instructions

Prepare your public key for inject into entrypoint with flag --epaddr. In example we will be using 0x4a0bfdAB7306b2Df31E26aF20fC423803625E4b6 address. Now you can run your node. In order to do it use following command:

{% code overflow="wrap" %}

```bash
docker run -d --name graphite-mainnet --network host -v ./graphite-data:/home/geth/data ghcr.io/atgraphite/graphite:v1.3.3 geth --datadir /home/geth/data --config /home/geth/config.toml --epaddr 0x4a0bfdAB7306b2Df31E26aF20fC423803625E4b6
```

{% endcode %}

Node rpc api is avaialable at <mark style="color:green;">**`http://127.0.0.1:8575`**</mark>

### **Usefull commands**

You can check node sync proggress with following command. If sync is done you will sync done message if not you will see elapsed blocks:

{% code overflow="wrap" %}

```bash
docker exec -it graphite-mainnet geth --exec 'eth.syncing.currentBlock == eth.syncing.highestBlock ? console.log("sync done") : console.log("sync in progress. elapse blocks: ", eth.syncing.highestBlock - eth.syncing.currentBlock);' attach /home/geth/data/geth.ipc
```

{% endcode %}

To attach node logs:

```bash
docker logs graphite-mainnet --follow
```

To interact node with graphite js console use following command:

```bash
docker exec -it graphite-mainnet geth attach /home/geth/data/geth.ipc
```


# Graphite Wallet

Graphite Wallet is an extension for accessing Graphite Network features and apps on Ethereum-compatible chains in your Chrome browser.

<figure><img src="/files/RipYgN1zCwnongvYrDkJ" alt="" width="375"><figcaption></figcaption></figure>

{% stepper %}
{% step %} <mark style="color:green;">**`Connect Graphite Wallet`**</mark>

Install the Graphite Wallet extension, create a new wallet or import mnemonic and come up with a password.
{% endstep %}

{% step %} <mark style="color:green;">**`Activate your account`**</mark>

Finish your preparations by hopping onto the Account Settings page and activating your account with a simple transaction.
{% endstep %}

{% step %} <mark style="color:green;">**`Explore!`**</mark>

Your account is good to go - feel free to tinker with your account settings, pass KYC measures, become a validator and put the Graphite Network to the test!
{% endstep %}
{% endstepper %}

***

{% embed url="<https://chromewebstore.google.com/detail/graphite-wallet/fbgdgmhhhlimaanngeakidegojjbbbbm>" %}
Graphite Wallet
{% endembed %}


# Graphite Web3 Documentation

## Basic Usage

* Detect the provider (<mark style="color:green;">**`window.graphite`**</mark>)
* Call the <mark style="color:green;">**`window.graphite.enable()`**</mark> method
* If access is granted, use the available api

## Available methods

### graphite.enable(): Promise\<string>

Calling this method triggers a user interface that allows a user to approve or reject account access for a given dApp. This method returns a Promise that is resolved with an account if the user approves access or is rejected with an Error if the user rejects access.

```js
await window.graphite.enable()
// If success:
// => 0xca8a66887dfbEf870a2d96de536986516a37fa12

// If regected:
// throw Error {
//  "code": -1,
//  "message": "User rejected the request."
//}
```

### graphite.isEnabled(): Promise\<bool>

Returns true if the dApp is already connected to a user's wallet, or if requesting access would return true without user confirmation (e.g. the dApp is whitelisted), and false otherwise.

```js
await window.graphite.isEnabled()
// => true
```

### graphite.request(): Promise\<Object>

JSON-RPC request to interact with the Graphite node.

```js
await window.graphite.request({
  "jsonrpc":"2.0",
  "method":"eth_getBalance",
  "params": ["0x1D9f2C01c8A20DcC59e806caFF5f46033e84ad2B", "latest"],
  "id":1
})
// => {
//    "jsonrpc": "2.0",
//    "id": 1,
//    "result": "0x6e9ce78211603c34113800"
// }
```

### graphite.getBalance(): Promise\<number>

JSON-RPC request to interact with the Graphite node.

```js
const balance = await window.graphite.getBalance()
// balance => 1094658474000000000
```

### graphite.getAddress(): Promise\<string>

Returns the active account.

```js
const account = await window.graphite.getAddress()
// account => '0xca8a66887dfbEf870a2d96de536986516a37fa12'
```

### graphite.getAccountInfo(): Promise\<object>

Returns basic account information, such as balance, activation status, KYC level and KYC filter.

```js
const info = await window.graphite.getAccountInfo()
// info => {
//    "balance": "0xf31021515242400",
//    "active": true,
//    "kycLevel": "1",
//    "kycFilterLevel": "2"
//    "reputation": "255"
//  }
```

### graphite.sendTx(params): Promise\<string>

To send a transaction, use the <mark style="color:green;">**`sendTx`**</mark> method where <mark style="color:green;">**`params`**</mark> is a options object. The wallet should ask the user for permission, and if given, try to sign and send transactions. This returns the transaction hash, if the transaction was submitted successfully, otherwise throws an <mark style="color:green;">**`error`**</mark>.

```js
const account = await window.graphite.getAddress()
const nonce = await window.graphite.request({
  "jsonrpc":"2.0",
  "method":"eth_getTransactionCount",
  "params": [account, "latest"],
  "id":1
})
const params = {
  nonce,
  from: account,
  to: '0x3526e99937B60E2CC18f10f6262B4D320FD2E371',
  value: '1000000000000',
  gasPrice: '18000000000',
  gas: '22000'
}
let hash = await window.graphite.sendTx(params)
// => '0x42d340b0e52ae61f0e004bd1939a3a8d23f02e6e09daf0ed402817948273e9ce'
```

### graphite.activateAccount(): Promise\<string>

To send transactions on Graphite, a user needs to activate their account. This can be done using the method <mark style="color:green;">**`activateAccount`**</mark>. The wallet should ask the user for permission to activate. This returns the transaction hash, if the transaction was submitted successfully, otherwise throws an <mark style="color:green;">**`error`**</mark>. The account balance must be non-zero.

```js
const hash = window.graphite.activateAccount()
// => {
// hash: '0x42d340b0e52ae61f0e004bd1939a3a8d23f02e6e09daf0ed402817948273e9ce',
// data: '0x1b9265b8'
// }
```

### graphite.updateKycLevel(level): Promise\<string>

To change the KYC level, use the method <mark style="color:green;">**`updateKycLevel`**</mark>. The wallet should ask the user for permission to change the level. Returns the transaction hash, if transaction was submitted successfully, otherwise throws an <mark style="color:green;">**`error`**</mark>. The account must already be activated and have a non-zero balance. The parameter <mark style="color:green;">**`level`**</mark> can be from 1 to 3.

<pre class="language-js"><code class="lang-js">const hash = window.graphite.updateKycLevel(1)
// => {
// hash: '0x42d340b0e52ae61f0e004bd1939a3a8d23f02e6e09daf0ed402817948273e9ce',
// uuid: 'd1c2b8a9-2976-4615-b7f4-2aca95a50123',
// data: '0x1a7106730000000000000000000000000000000000000000000000000000000000000001e8f2c758111c95c39485e683ad7f24c53c0aca399c0edea39532bda5e2b95c11'
<strong>// }
</strong></code></pre>

### graphite.updateKycFilter(filter): Promise\<string>

To change the KYC filter, use the method <mark style="color:green;">**`updateKycFilter`**</mark>. The wallet should ask the user for permission to change the filter. Returns the transaction hash, if transaction was submitted successfully, otherwise throws an <mark style="color:green;">**`error`**</mark>. The account must already be activated and have a non-zero balance. The parameter <mark style="color:green;">**`filter`**</mark> can be from 1 to 3.

```js
const hash = window.graphite.updateKycFilter(2)
// => { 
// hash: '0x42d340b0e52ae61f0e004bd1939a3a8d23f02e6e09daf0ed402817948273e9ce',
// data: '0xd1a23b900000000000000000000000000000000000000000000000000000000000000001'
// }
```

### graphite.getLastKycRequest(): Promise\<Object>

Returns the latest KYC request data for the user based on the active network.

<pre class="language-javascript"><code class="lang-javascript">const lastKycRequest = await window.graphite.getLastKycRequest()
// lastKycRequest => {
//  "address":"0x9684055b99332231F34C27423a0A9d968dBC6379",
//  "lastKycTxHash":"0x42d340b0e52ae61f0e004bd1939a3a8d23f02e6e09daf0ed402817948273e9ce",
//  "centre": "0x8D8129f2F56D87F39a3dEA1ba33a3bd930849F81",
//  "deposite": "0",
<strong>//  "level": "1",
</strong><strong>//  "status": "0",
</strong>//  "statusName": "pending",
//  "uuid": "d05875e9-c9b0-4312-a349-874f6ef317df"
<strong>// }
</strong></code></pre>

### graphite.getActiveNetwork(): Promise<"mainnet" | "testnet">

Returns whether the active network is testnet or mainnet.

<pre class="language-javascript"><code class="lang-javascript">const activeNetwork = await window.graphite.getActiveNetwork()
<strong>// getActiveNetwork =>  "mainnet"
</strong></code></pre>

### graphite.changeActiveNetwork(network: "mainnet" | "testnet"): Promise<"mainnet" | "testnet">

Changes the active network to either testnet or mainnet and returns the updated network.

<pre class="language-javascript"><code class="lang-javascript">const changeActiveNetwork = await window.graphite.changeActiveNetwork("testnet")
<strong>// changeActiveNetwork =>  "testnet"
</strong></code></pre>


# Graphite Bridge

Simple way to transfer Graphite into various networks.

## Overview

Graphite Bridge offers a seamless solution for transferring Graphite assets across different networks. This tool enables users to bridge assets, expanding Graphite's utility and reach beyond a single blockchain ecosystem.

<figure><img src="/files/c2Y90XX9E3En19fyRa9T" alt=""><figcaption></figcaption></figure>

## How to Use

{% stepper %}
{% step %} <mark style="color:green;">**`Log in`**</mark>&#x20;

To access Graphite Bridge, you need to log into your Graphite Wallet. Logging in ensures secure authentication and access to bridging services.
{% endstep %}

{% step %} <mark style="color:green;">**`Select Destination Network`**</mark>

Choose the network where you want to transfer your Graphite assets. The bridge supports various popular networks, facilitating compatibility and cross-network transactions.
{% endstep %}

{% step %} <mark style="color:green;">**`Confirm Transfer`**</mark>

Once the destination is set, review and confirm the transfer. The bridge manages the technical steps, requiring minimal user input.
{% endstep %}
{% endstepper %}

***

{% embed url="<https://bridge.atgraphite.com>" %}
Bridge Mainnet Graphite&#x20;
{% endembed %}

{% embed url="<https://test.bridge.atgraphite.com>" %}
Bridge Testnet Graphite&#x20;
{% endembed %}

***


# The Graphite Explorer

Explore how to view blocks, transactions, tokens, addresses, and more on Graphite block explorers.

With <mark style="color:green;">**Graphite Explorer**</mark>, gaining insights into blockchain data has never been easier:

<figure><img src="/files/JrAfCoFGwPjuWA9JcUu8" alt="" width="563"><figcaption></figcaption></figure>

* View and verify smart contract source code.
* Track transaction, block and token details in real-time.
* Explore address activity and token holdings.
* Monitor the status of transactions and network performance.

***

{% embed url="<https://main.atgraphite.com>" %}
The Graphite Explorer Mainnet
{% endembed %}

{% embed url="<https://test.atgraphite.com>" %}
The Graphite Explorer Testnet
{% endembed %}

***


# API documentation

Below is a sample **GET** request along with its corresponding response, taken from the API documentation of The Graphite Explorer. For a more comprehensive understanding of the available endpoints, parameters, and response formats, we encourage you to explore [<mark style="color:green;">**the full documentation**</mark>](< https://docs.main.atgraphite.com/>).

### <mark style="color:green;">Example:</mark> Accounts - Get balance for a single address

Returns the balance of a given address.

**Sample request**

```javascript
https://api.main.atgraphite.com/api
   ?module=account
   &action=balance
   &address=0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae
   &tag=latest
   &apikey=YourApiKeyToken
```

**Request query parameters**

<table><thead><tr><th width="138">Parameter</th><th>Description</th></tr></thead><tbody><tr><td>address*</td><td>the string representing the address to check for balance</td></tr><tr><td>tag*</td><td>the string pre-defined block parameter, either <mark style="color:green;"><strong><code>earliest</code></strong></mark>, <mark style="color:green;"><strong><code>pending</code></strong></mark> or <mark style="color:green;"><strong><code>latest</code></strong></mark></td></tr></tbody></table>

**Sample response**

{% code fullWidth="false" %}

```json
{
    "status": "1",
    "message": "OK",
    "result": "40891626854930000000000" 
}
```

{% endcode %}

<mark style="color:green;">**The full documentation**</mark> can be found at the link below:

{% embed url="<https://docs.main.atgraphite.com/>" %}


# Faucet Testnet

Easily get testnet funds for development on Graphite.

[<mark style="color:green;">**The Graphite Faucet**</mark>](https://faucet.atgraphite.com) is a simple tool to quickly obtain <mark style="color:green;">**`testnet`**</mark> funds for development on the Graphite network. With just a few clicks, developers can access the necessary resources to test and build their projects efficiently.&#x20;

***

{% embed url="<https://faucet.atgraphite.com>" %}
The Graphite Testnet Faucet&#x20;
{% endembed %}

***


# Phonebook Reputation MVP

### Overview <a href="#overview" id="overview"></a>

Phonebook lets you look up phone numbers and check their reputation through community votes. All data is stored in blockchain smart contracts. Each number gets a reputation score, calculated by flexible algorithms in smart contracts. To vote, connect your wallet and verify your number.&#x20;

<figure><img src="/files/2YcQkAozFv2pv5GEVrZ5" alt=""><figcaption></figcaption></figure>

### How to Use <a href="#how-to-use" id="how-to-use"></a>

{% stepper %}
{% step %} <mark style="color:green;">**`Connect Your Wallet`**</mark>

To use Phonebook, connect your MetaMask or Graphite Wallet. This ensures secure identity verification and access to the platform.
{% endstep %}

{% step %} <mark style="color:green;">**`Complete Registration`**</mark>

Registration requires two steps:

* Pay a  network fee
* Verify your phone number

Once completed, you’ll receive <mark style="color:green;">**`100 tokens`**</mark> that can be used to assign reputation to phone numbers.

⚠️ Note: Tokens are one-time only — they do **not** replenish.
{% endstep %}

{% step %} <mark style="color:green;">**`Vote on a Number`**</mark>

To assign a reputation score to a phone number:

* Enter the phone number
* Choose how many tokens you want to spend
* Select a **positive** or **negative** reputation
* Confirm the transaction

***

That’s it — the number now has a reputation!\
Want to learn how reputation is calculated? Check [<mark style="color:green;">here</mark>](/ecosystem/phonebook-reputation-mvp/how-it-works).
{% endstep %}
{% endstepper %}

***

{% embed url="<https://phonebook.atgraphite.com/>" %}
Phonebook
{% endembed %}


# How it works?

### What is a reputation system?

Our reputation system allows Graphite users to build trust around phone numbers - people can vote for numbers they personally trust, for businesses they support or against spammers, frauds and malicious actors. The system is transparent and reputation is built solely by our users.

### How voting works?

To avoid abuse and help build more reliable reputation we rely not only on plain user votes, but also account for each user's personal voting history and vote's historical relevance.

This way, not all votes are equal - the most just users and fresh votes have more weight applied to a phone number reputation than people who are trying to review-bomb someone or have a more outdated opinion

### How weighting works?

The most simple explanation is that your clear vote is being amplified by other values

E.g., you vote +50 on some phone number. In a clear system without any weights your vote would be applied "as is" and would be counted along all the other votes equally. But in Graphite, your vote is only a part of what's applied to the reputation. After receiving your vote, we extend it from a -100 to +100 scale of votes to a more complex scale of reputation, which goes from -1000 to 1000

We do so by applying various weights, which combined can amplify your vote up to 10 times from its original value. This way, your +50 vote could easily impact a phone's reputation by +500 if the system sees you as a just person. The same way, someone with a malicious intent of, for example ruining his business competitor's reputation, could impact it down to 5 times less serious than someone with clear intents

### User voting history weight

For user voting history we use a sigmoid function with custom parameters. This function calculates the weight in a range from 1 to 5 based on the user's history of giving negative or positive reviews. Currently, this only accounts for the fact if each review was either positive or negative, calculates the ratio and gives it a san input to the weight function. The closer this ratio to 1 (the more balanced the user votes), the higher weight the user will receive

### Vote time relevance weight

For historical relevance we also use the same sigmoid function. This weight calculates the relevance of each vote given their relevant position in the list of calculated votes. The newer the vote is - the higher its weight will be

### Calculating reputation

Given the weights of each vote as described above, reputation is calculated as a weighted average of all the votes, that were submitted for the target phone number. Each vote has its weights added to it, all votes and their weights are summed up and divided by the overall amount of votes submitted

### Revoting

There is also a possibility to change your vote at any time. For example, a reliable business partner, for whom you voted positively before, suddenly changed his behavior and now you want to give him a negative review instead. In that case, you can revote - the system will automatically delete your previous vote and create a new one. This new vote will be taken into account as a fresh and relevant one, so both weights will be recalculated again - based on your current voting behavior as well


# @G Bonus Guide

### **Overview**

When purchasing **@G** tokens on the [<mark style="color:green;">**BUY Graphite**</mark>](https://atgraphite.com/buy-graphite) page, buyers have the opportunity to increase the total amount of tokens they receive through the bonus program.\
You can choose either to receive all tokens instantly or to receive part immediately and the remainder one month later along with a **+10% bonus**.

This article explains how the bonus system works, what options are available, and how to claim your bonus after the lock-up period ends.

### **Token Receipt Options**

Before purchasing @G tokens, two options for receiving them are available.

#### **Option 1. Receive 100% Immediately (No Bonus)**

The user receives the entire purchased amount of tokens instantly. To use this option, **do not check** the *“I want a 10% bonus”* box.

**Result:&#x20;**<mark style="color:green;">**100% of purchased tokens are available immediately.**</mark>

#### **Option 2. Receive a +10% Bonus After 1 Month**

To use the bonus program, the user must **check the** *“I want a 10% bonus”* **box**.

In this case, tokens are distributed in two stages:

1. **Immediately:** 80% of the purchased tokens
2. **After 30 days:** 20% locked tokens + an additional 10% bonus

This means that after one month, the user receives both the remaining locked tokens and the extra bonus.

**Result:**

* <mark style="color:green;">**Immediately: 80%**</mark>
* <mark style="color:green;">**After 30 days: 20% + 10% bonus**</mark>

This option allows the buyer to increase their total amount of tokens by waiting 1 month.

### **How the Bonus Lock Works**

When the bonus option is selected:

* 20% of the purchased tokens are automatically locked (staked).
* The lock-up period lasts **30 days** from the moment of purchase.
* After the period ends, the user can claim:
  * the locked 20%, and
  * the additional **+10% bonus**

### **How to Claim the Bonus After 1 Month**

After the 30-day lock-up period ends, the user must:

1. Go to the [<mark style="color:green;">**account page**</mark>](https://atgraphite.com/account) on the Graphite website
2. Log in using the **same address that was provided during the token purchase**
3. Open the **Bonus** section
4. Click **Claim** to receive:
   * the unlocked 20%
   * the additional 10% bonus

The tokens will then become available on the user’s address.

{% hint style="warning" %}
If the bonus claim option is not available, it likely means that **30 days have not yet passed** since the purchase.

If you have any additional questions, please contact us at [**support@atgraphite.com**](mailto:support@atgraphite.com)
{% endhint %}


