# EOSIO.token <> EOSIO.token Fungible Tokens

This guide will essentially map the [`tokenpeg.spec.js`](https://github.com/liquidapps-io/zeus-sdk/blob/master/boxes/groups/sample/tokenpeg/test/tokenpeg.spec.js) unit test.&#x20;

Resources:

* Block Explorers:
  * <https://kylin.bloks.io/>
  * <https://jungle3.bloks.io/>
  * <https://kylin.eosq.eosnation.io/>
  * <https://jungle.eosq.eosnation.io/>
* DSP Portals
  * <https://dsphq.liquidapps.io/>
* Faucet:
  * <https://kylin-dapp-faucet.liquidapps.io/>

Steps:

* [Install Zeus](/liquidapps-documentation/working-with-zeus-sdk/overview/install-zeus-and-unboxing.md) if not installed, zeus is used to unbox or install all the necessary dependencies to compile and deploy the necessary contracts.

{% hint style="warning" %}
Ensure you're using node version 12, IPFS can be picky with other versions
{% endhint %}

* [Unbox](/liquidapps-documentation/working-with-zeus-sdk/overview/install-zeus-and-unboxing.md) `tokenpeg` box

```bash
mkdir tokenpeg; cd tokenpeg
zeus box create
zeus unbox tokenpeg
```

* Add LiquidX mapping file

`/zeus_boxes/liquidx/models/eosio-chains/liquidjungl3.json`

The following file is for the destination's chain information.&#x20;

```bash
# remove existing JSON file to not confuse the compiler
rm -rf ./zeus_boxes/liquidx/models/eosio-chains/
mkdir ./zeus_boxes/liquidx/models/eosio-chains/
touch ./zeus_boxes/liquidx/models/eosio-chains/liquidjungl3.json
vim ./zeus_boxes/liquidx/models/eosio-chains/liquidjungl3.json
```

```javascript
{
  "dsp_port": 3117,
  "webhook_dapp_port": 8813,
  "nodeos_host": "jungle3.cryptolions.io",
  "nodeos_port": 443,
  "secured": true,
  "nodeos_state_history_port": 8887,
  "nodeos_p2p_port": 12451,
  "nodeos_endpoint": "https://jungle3.cryptolions.io:443",
  "demux_port": 1232,
  "name": "liquidjungl3",
  "local": false
}
```

`/zeus_boxes/liquidx/models/liquidx-mappings/sidechain_name.dappservices.json`

This file allows for the compiler to insert relevant chain information into the contract header.

```bash
# remove existing JSON
rm -rf ./zeus_boxes/liquidx/models/liquidx-mappings/
mkdir ./zeus_boxes/liquidx/models/liquidx-mappings/
touch ./zeus_boxes/liquidx/models/liquidx-mappings/liquidjungl3.dappservices.json
vim ./zeus_boxes/liquidx/models/liquidx-mappings/liquidjungl3.dappservices.json
```

```javascript
{
  "sidechain_name": "liquidjungl3",
  "mainnet_account": "dappservices",
  "chain_account": "testdappxxxx"
}
```

* Compile contracts

```bash
zeus compile tokenpeg; zeus compile tokenpegx
```

{% hint style="info" %}
Examine `./contracts/eos/dappservices/dappservices.config.hpp` and you will see the mapping field populate into c++ definitions, if you see `TEST1`, you need to delete the existing mapping files
{% endhint %}

* Create 3 [Kylin](/liquidapps-documentation/eosio-guides/testnet-creation-guides/creating-cryptokylin-account.md) and 3 [Jungle Accounts](/liquidapps-documentation/eosio-guides/testnet-creation-guides/creating-jungle-3-account.md)
  * Kylin token contract Account (token being bridged `eosio.token.cpp`)
  * Kylin bridge contract Account (`tokenpeg.cpp`)
  * Kylin test Account **no contract**
  * Jungle token contract Account (token on Jungle to mint/burn tokens `eosio.token.cpp`)
  * Jungle bridge contract Account (`tokenpegx.cpp`)
  * Jungle test Account **no contract**

```bash
export KYLIN_BRIDGE_ACCOUNT=tokenexample
export KYLIN_TOKEN_ACCOUNT=token4bridge
export KYLIN_TEST_ACCOUNT=natdeveloper
export KYLIN_ENDPOINT=https://kylin.eosn.io
export JUNGLE_BRIDGE_ACCOUNT=tokenexample
export JUNGLE_TOKEN_ACCOUNT=token4bridge
export JUNGLE_TEST_ACCOUNT=natdeveloper
export JUNGLE_ENDPOINT=https://jungle3.cryptolions.io:443
```

* Setup `tokenpeg` on the **Kylin token contract Account** and `tokenpegx` on the **Jungle token contract Account** using `zeus migrate`.
* Import private keys

```bash
zeus key import $KYLIN_BRIDGE_ACCOUNT --owner-private-key 5JPPPML... --active-private-key 5KdLRibwg1v... --network=kylin
zeus key import $JUNGLE_BRIDGE_ACCOUNT --owner-private-key 5KkDxt... --active-private-key 5KkDxtfyKQQ... --network=jungle3
zeus key import $KYLIN_TOKEN_ACCOUNT --owner-private-key 5JPPPML... --active-private-key 5KdLRibwg1v... --network=kylin
zeus key import $JUNGLE_TOKEN_ACCOUNT --owner-private-key 5KkDxt... --active-private-key 5KkDxtfyKQQ... --network=jungle3
```

* Create contract deployment files located in `./zeus_boxes/contract-migrations-extensions/models/contract-deployments/`

```bash
zeus create contract-deployment tokenpeg $KYLIN_BRIDGE_ACCOUNT kylin
zeus create contract-deployment tokenpegx $JUNGLE_BRIDGE_ACCOUNT jungle3
zeus create contract-deployment eosio.token $KYLIN_TOKEN_ACCOUNT kylin
zeus create contract-deployment eosio.token $JUNGLE_TOKEN_ACCOUNT jungle3
```

* Migrate contracts to Kylin/Jungle

{% tabs %}
{% tab title="Zeus Migrate" %}

```bash
zeus migrate tokenpeg --network=kylin --creator $KYLIN_BRIDGE_ACCOUNT --no-reset --no-compile-all --creator-key=""
zeus migrate tokenpegx --network=jungle3 --creator $JUNGLE_BRIDGE_ACCOUNT --no-reset --no-compile-all --creator-key=""
zeus migrate eosio.token --network=kylin --creator $KYLIN_TOKEN_ACCOUNT --no-reset --no-compile-all --creator-key=""
zeus migrate eosio.token --network=jungle3 --creator $JUNGLE_TOKEN_ACCOUNT --no-reset --no-compile-all --creator-key=""
```

{% endtab %}

{% tab title="cleos set contract" %}

```bash
# if migration fails
cd contracts/eos
cleos -u $KYLIN_ENDPOINT set contract $KYLIN_BRIDGE_ACCOUNT tokenpeg
cleos -u $JUNGLE_ENDPOINT set contract $JUNGLE_BRIDGE_ACCOUNT tokenpegx
cleos -u $KYLIN_ENDPOINT set contract $KYLIN_TOKEN_ACCOUNT eosio.token
cleos -u $JUNGLE_ENDPOINT set contract $JUNGLE_TOKEN_ACCOUNT eosio.token
```

{% endtab %}
{% endtabs %}

* Initialize token contracts
* Create

Create tokens

For Kylin, we'll set the `issuer` to the token contract, this is to simulate a pre-existing token that is being bridged to Jungle3. &#x20;

Only Jungle3 we will set the `issuer` to the bridge contract so that it can issue tokens when they come across the bridge. We will also issue those tokens to the&#x20;

{% tabs %}
{% tab title="Kylin" %}

```bash
export MAX_SUPPLY="1000000.0000 TKN"
export ISSUER=$KYLIN_TOKEN_ACCOUNT # token contract itself
cleos -u $KYLIN_ENDPOINT push action $KYLIN_TOKEN_ACCOUNT create "[\"$ISSUER\",\"$MAX_SUPPLY\"]" -p $KYLIN_TOKEN_ACCOUNT@active
```

{% endtab %}

{% tab title="Jungle3" %}

```bash
export MAX_SUPPLY="1000000.0000 TKN"
export ISSUER=$JUNGLE_BRIDGE_ACCOUNT # bridge contract so it can issue/burn
cleos -u $JUNGLE_ENDPOINT push action $JUNGLE_TOKEN_ACCOUNT create "[\"$ISSUER\",\"$MAX_SUPPLY\"]" -p $JUNGLE_TOKEN_ACCOUNT@active
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
If you get errors such as **Transaction exceeded the current network usage limit imposed on the transaction**, see the [Kylin](/liquidapps-documentation/eosio-guides/testnet-creation-guides/creating-cryptokylin-account.md) / [Jungle](/liquidapps-documentation/eosio-guides/testnet-creation-guides/creating-jungle-3-account.md) account setup guides to get more tokens and to stake for more resources.
{% endhint %}

* Issue test tokens

We will issue some test tokens to our test account.

```bash
export TO=$KYLIN_TOKEN_ACCOUNT
export QUANTITY="10.0000 TKN"
export MEMO="issuing tokens"
cleos -u $KYLIN_ENDPOINT push action $KYLIN_TOKEN_ACCOUNT issue "[\"$TO\",\"$QUANTITY\",\"$MEMO\"]" -p $KYLIN_TOKEN_ACCOUNT@active
```

* Transfer test tokens

Now we will transfer the issued tokens to the test account.

```bash
export FROM=$KYLIN_TOKEN_ACCOUNT
export TO=$KYLIN_TEST_ACCOUNT
export QUANTITY="10.0000 TKN"
export MEMO="don't spend it all in one place!"
cleos -u $KYLIN_ENDPOINT push action $KYLIN_TOKEN_ACCOUNT transfer "[\"$FROM\",\"$TO\",\"$QUANTITY\",\"$MEMO\"]" -p $KYLIN_TOKEN_ACCOUNT@active
```

* Stake for services

Now that we've prepared that part let's move onto staking DAPP for services. First stop is the faucet for some DAPP tokens [here](https://kylin-dapp-faucet.liquidapps.io/). Use the account that has the `tokenpeg` contract set to it.

* Stake to required services vRAM, LiquidHarmony Oracles, and LiquidScheduler

Below we'll select each package then stake for it.

{% tabs %}
{% tab title="vRAM" %}

```bash
export PROVIDER=uuddlrlrbass
export PACKAGE=ipfs2
export SERVICE=ipfsservice1
export QUANTITY="10.0000 DAPP"
cleos -u $KYLIN_ENDPOINT push action dappservices selectpkg "[\"$KYLIN_BRIDGE_ACCOUNT\",\"$PROVIDER\",\"$SERVICE\",\"$PACKAGE\"]" -p $KYLIN_BRIDGE_ACCOUNT@active
cleos -u $KYLIN_ENDPOINT push action dappservices stake "[\"$KYLIN_BRIDGE_ACCOUNT\",\"$PROVIDER\",\"$SERVICE\",\"$QUANTITY\"]" -p $KYLIN_BRIDGE_ACCOUNT@active
```

{% endtab %}

{% tab title="LiquidHarmony" %}

```bash
export PROVIDER=uuddlrlrbass
export PACKAGE=oracleservi2
export SERVICE=oracleservic
export QUANTITY="10.0000 DAPP"
cleos -u $KYLIN_ENDPOINT push action dappservices selectpkg "[\"$KYLIN_BRIDGE_ACCOUNT\",\"$PROVIDER\",\"$SERVICE\",\"$PACKAGE\"]" -p $KYLIN_BRIDGE_ACCOUNT@active
cleos -u $KYLIN_ENDPOINT push action dappservices stake "[\"$KYLIN_BRIDGE_ACCOUNT\",\"$PROVIDER\",\"$SERVICE\",\"$QUANTITY\"]" -p $KYLIN_BRIDGE_ACCOUNT@active
```

{% endtab %}

{% tab title="LiquidScheduler" %}

```bash
export PROVIDER=uuddlrlrbass
export PACKAGE=cronservice2
export SERVICE=cronservices
export QUANTITY="10.0000 DAPP"
cleos -u $KYLIN_ENDPOINT push action dappservices selectpkg "[\"$KYLIN_BRIDGE_ACCOUNT\",\"$PROVIDER\",\"$SERVICE\",\"$PACKAGE\"]" -p $KYLIN_BRIDGE_ACCOUNT@active
cleos -u $KYLIN_ENDPOINT push action dappservices stake "[\"$KYLIN_BRIDGE_ACCOUNT\",\"$PROVIDER\",\"$SERVICE\",\"$QUANTITY\"]" -p $KYLIN_BRIDGE_ACCOUNT@active
```

{% endtab %}
{% endtabs %}

* LiquidX stake

In order to stake for services on Jungle3, a LiquidX mapping must be created, for more detail see [here](/liquidapps-documentation/liquidx-stake-across-chains/getting-started-with-liquidx/use-dapp-network-services.md).

{% tabs %}
{% tab title="Kylin" %}

```bash
export OWNER=$KYLIN_BRIDGE_ACCOUNT
export CHAIN_ACCOUNT=$JUNGLE_BRIDGE_ACCOUNT
export CHAIN_NAME=liquidjungl3
cleos -u $KYLIN_ENDPOINT push action liquidxxxxxx addaccount "[\"$OWNER\",\"$CHAIN_ACCOUNT\",\"$CHAIN_NAME\"]" -p $KYLIN_BRIDGE_ACCOUNT@active
```

{% endtab %}

{% tab title="Jungle3 setlink" %}

```bash
export OWNER=$JUNGLE_BRIDGE_ACCOUNT
export MAINNET_OWNER=$KYLIN_BRIDGE_ACCOUNT
cleos -u $JUNGLE_ENDPOINT push action testdappxxxx setlink "[\"$OWNER\",\"$MAINNET_OWNER\"]" -p $JUNGLE_BRIDGE_ACCOUNT@active
```

{% endtab %}

{% tab title="Jungle3 add dsp" %}

```bash
export OWNER=$JUNGLE_BRIDGE_ACCOUNT
export DSP=$PROVIDER
cleos -u $JUNGLE_ENDPOINT push action testdappxxxx adddsp "[\"$OWNER\",\"$DSP\"]" -p $JUNGLE_BRIDGE_ACCOUNT@active
```

{% endtab %}
{% endtabs %}

* Initialize

Here we will initialize both bridges with their settings.  On Kylin we will not allow issuance because the token already exists.  On Jungle we allow the bridge contract to issue tokens to mint/burn.  We set the minimum transfer to 1 TKN.

{% tabs %}
{% tab title="Kylin" %}

```bash
export SISTER_CODE=$JUNGLE_BRIDGE_ACCOUNT
export SISTER_CHAIN_NAME="liquidjungl3"
export THIS_CHAIN_NAME="kylin"
export PROCESSING_ENABLED=1
export TOKEN_CONRACT=$KYLIN_TOKEN_ACCOUNT
export TOKEN_SYMBOL="4,TKN"
export MIN_TRANSFER=10000
export TRANSFERS_ENABLED=1
export CAN_ISSUE=0
export KYLIN_DSP_ENDPOINT=http://kylin-dsp-2.liquidapps.io
cleos -u $KYLIN_ENDPOINT push action $KYLIN_BRIDGE_ACCOUNT init "[\"$SISTER_CODE\",\"$SISTER_CHAIN_NAME\",\"$THIS_CHAIN_NAME\",\"$PROCESSING_ENABLED\",\"$TOKEN_CONRACT\",\"$TOKEN_SYMBOL\",\"$MIN_TRANSFER\",\"$TRANSFERS_ENABLED\",\"$CAN_ISSUE\"]" -p $KYLIN_BRIDGE_ACCOUNT@active
```

{% endtab %}

{% tab title="Jungle3" %}

```bash
export SISTER_CODE=$KYLIN_BRIDGE_ACCOUNT
export SISTER_CHAIN_NAME="kylin"
export THIS_CHAIN_NAME="liquidjungl3"
export PROCESSING_ENABLED=1
export TOKEN_CONRACT=$JUNGLE_TOKEN_ACCOUNT
export TOKEN_SYMBOL="4,TKN"
export MIN_TRANSFER=10000
export TRANSFERS_ENABLED=1
export CAN_ISSUE=1
cleos -u $JUNGLE_ENDPOINT push action $JUNGLE_BRIDGE_ACCOUNT init "[\"$SISTER_CODE\",\"$SISTER_CHAIN_NAME\",\"$THIS_CHAIN_NAME\",\"$PROCESSING_ENABLED\",\"$TOKEN_CONRACT\",\"$TOKEN_SYMBOL\",\"$MIN_TRANSFER\",\"$TRANSFERS_ENABLED\",\"$CAN_ISSUE\"]" -p $JUNGLE_BRIDGE_ACCOUNT@active
```

{% endtab %}
{% endtabs %}

* Transfer

Now we will test with a transfer from the Kylin example user to the Kylin bridge contract, let's see how it goes!!

{% tabs %}
{% tab title="Kylin" %}

```bash
export FROM=$KYLIN_TEST_ACCOUNT
export TO=$KYLIN_BRIDGE_ACCOUNT
export QUANTITY="10.0000 TKN"
# destionation_account,destination_chain
# this is required as the memo type, it tells the bridge which chain the funds go to and who gets them
export MEMO="$JUNGLE_TEST_ACCOUNT,liquidjungl3"
cleos -u $KYLIN_ENDPOINT push action $KYLIN_TOKEN_ACCOUNT transfer "[\"$FROM\",\"$TO\",\"$QUANTITY\",\"$MEMO\"]" -p $KYLIN_TEST_ACCOUNT@active
```

{% endtab %}
{% endtabs %}

* Confirm

If all goes well you will see the tokens arrive at your Jungle destination account, you can send them back to the bridge contract now to send them back!&#x20;

{% tabs %}
{% tab title="Jungle3" %}

```bash
export FROM=$JUNGLE_TEST_ACCOUNT
export TO=$JUNGLE_BRIDGE_ACCOUNT
export QUANTITY="10.0000 TKN"
# destionation_account,destination_chain
# this is required as the memo type, it tells the bridge which chain the funds go to and who gets them
export MEMO="$KYLIN_TEST_ACCOUNT,kylin"
cleos -u $JUNGLE_ENDPOINT push action $JUNGLE_TOKEN_ACCOUNT transfer "[\"$FROM\",\"$TO\",\"$QUANTITY\",\"$MEMO\"]" -p $JUNGLE_TEST_ACCOUNT@active
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Note that the memo destination chain is now `kylin` and no longer `liquidjungl3` because we are sending the tokens to `kylin`.
{% endhint %}

{% hint style="warning" %}
If the transfers are not going through, ensure that the DSP you are using has enough CPU/NET staked for it
{% endhint %}


---

# Agent Instructions: Querying This Documentation

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

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

```
GET https://docs.liquidapps.io/liquidapps-documentation/cross-chain-bridges/getting-started-with-liquidbridge/eosio-less-than-greater-than-eosio.md?ask=<question>
```

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

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