# Pirichain Smart Scenario (PSce)

This page will explain how to use Pirichain Smart Scenarios (PSce), how it will bring benefications to any kind of industry.

![](/files/KSgIPOcDOQO2PGVuTstW)

Smart scenarios **don't only operate** in the context of decentralized finance. They are also quite useful for very specific industries. Within the system, handling and generating data have been simplified with basic functions, allowing you to easily write the necessary code for your own ecosystem without requiring advanced expertise.

Connecting smart scenarios to external environments is actually a groundbreaking development. Why? Working with the latest real-time data will greatly benefit your ecosystem. And you cannot make healthy desicion if you cannot connect other systems. Operating in this way brings many innovations to the blockchain sector as well.

You can find more samples in :[ https://piriscan.com/scenarios ](<https://piriscan.com/scenarios >)


# Which Industries can use easily PSces?

**Financial Services:** Smart scenarios and integration with external environments can make financial transactions faster and more efficient. For example, it can be used in areas such as payment systems, credit processing and trade finance.

**Health:** In the health sector, it can be used in the management of processes such as hospital records, medication monitoring and patient follow-up. Real-time data integration can help make healthcare more effective and reliable.

**Logistics and Supply Chain:** Smart scenarios can be used to optimize logistics and supply chain management. Real-time information integration can be achieved in product tracking, inventory management and transportation processes.

**Energy:** In the energy sector, smart scenarios can be used in areas such as energy trading, consumption monitoring and renewable energy projects. Data integration can make energy management more effective.

**Education:** Smart scenarios can be used in the education sector in areas such as student monitoring, certificate management and student performance analysis. It can make educational processes more transparent and reliable.

**Smart Cities:** Can be used for city management, traffic management, garbage monitoring, energy efficiency and other smart city applications.

**Agriculture:** It can be used in the agricultural sector in areas such as product monitoring, soil analysis and irrigation systems. Real-time data integration can make farming processes more effective.\
\
**Real Estate:** Can be used in real estate sales and rental. Smart contracts can make the transfer of ownership faster and more secure.

**Insurance:** Smart scenarios can process insurance claims faster and automate payment processes.

**Art and Culture:** Can be used to track works of art, ownership changes and copyright management.

**Retail:** Can be used in areas such as stock management, loyalty programs and payment systems.

**Tourism and Hospitality:** Can be used to optimize reservation management, customer loyalty and payment processing.

**Telecommunication:** It can be used in processes such as mobile payments, subscription management and device tracking.

**Legal and Secondary Markets:** Smart contracts can be used for automatically executed legal transactions and secondary market transactions.

**Food Safety:** Food supply chain monitoring can be used for product reliability and tracking.

**Film and Media:** Can be used for copyright management, content monitoring and revenue sharing.

**Gaming Industry:** Smart scripts can be used to optimize gaming industry processes such as tracking, selling and transferring in-game assets.

**Human Resources:** It can be used in human resources processes such as recruitment processes, performance management and personnel management.

**Technology and Innovation:** Can be used in innovation processes such as patent management, product tracking and supply chain management.

**Social Assistance and Donation:** Donation management can be used to provide transparency in aid distribution and social aid processes.

**Music Industry:** Can be used to optimize copyright management, revenue sharing and music licensing processes.

**Aviation and Transportation:** Can be used in flight monitoring, maintenance management and logistics processes.

**E-commerce:** It can be used in e-commerce processes such as payment systems, customer loyalty and stock management.

**Research and Development:** Can be used for scientific data sharing, project financing and optimizing research processes.

**Maritime and Port Management:** Can be used for port operations monitoring, cargo tracking and maritime logistics.

**Food and Beverage Industry:** It can be used in food safety monitoring, supply chain management and quality control processes.


# Full Support Interoperability!

<figure><img src="/files/aByUKu6fJvc9OFLH6tcb" alt=""><figcaption><p>A sample of Interoperability in PCse's</p></figcaption></figure>

One of the key distinctions of Pirichain's Smart Scenarios from other systems is its ability to seamlessly integrate with external environments. Systems supporting smart contracts often lack the capability to connect with external environments, limiting their ability to provide an interactive environment. Pirichain's Smart Scenarios, with this feature, become the first blockchain to introduce interactivity, a crucial element for every industry.

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


# General Structure of Smart Scenarios

Pirichain Smart Scenarios (PSce) supports to written by JavaScript or TypeScript Language. And It can handle multiple operation in one PSce.

```
What can I do using with PSce?
    * Multiple Asset Managements
    * Data Managements - Data Analyse ,Query,Generate at run time.
    * Full Integrate with external Environments.
    * Data Encryption
    * Link with other blockchain system helps with Web3 Library
     
```

Below new features comes valuable benefitions;&#x20;

1. **Real-Time Data Integration:** External connections enable your ecosystem system to fetch real-time data from various sources. This is crucial for applications that require up-to-date information, like financial transactions, market prices, or IoT data.
2. **Increased Functionality:** Integrating with external services expands the functionality of  blockchain system. It allows your system to leverage the capabilities of other platforms and services, enhancing overall utility.
3. **Interoperability:** Connecting to external environments promotes interoperability between different systems. It enables your ecosystem to work seamlessly with existing technologies and ecosystems, fostering collaboration and integration across diverse platforms.
4. **Wider Adoption:** The ability to interact with external systems makes your ecosystem more versatile and applicable to a broader range of use cases. This, in turn, can attract more users and developers to adopt and contribute to your ecosystem ecosystem.
5. **Enhanced Decentralization:** While the blockchain itself is decentralized, connecting to external data sources can decentralize the information flow. This ensures that data is not controlled by a single entity and contributes to the overall decentralization philosophy.
6. **Smart Contract Automation:** External connections can facilitate the automation of smart contracts by providing real-world data inputs. This is particularly valuable for decentralized applications (DApps) that require external information to trigger and execute certain actions autonomously.
7. **Improved User Experience:** Access to real-time, external data can enhance the user experience by providing accurate and timely information. This is especially important in applications where users rely on the latest data for decision-making.

In summary, connecting a new blockchain system to external environments opens up a world of possibilities, bringing benefits such as real-time data, expanded functionality, interoperability, wider adoption, enhanced decentralization, smart contract automation, and improved user experiences.

<br>

## Beyond the thoughts

Pirichain has powerful blockchain system that can solve many problems with low costs.&#x20;


# PSce Working Principles And Limitations

PSce works similar to EVM based system. But there is no necessary specific language such as solidity. Because most of programmers know that the Javascript.

***A wallet can create unlimited PSce.***&#x20;

PSce can create new transactions depend on your code. ***But count of Maximum transactions must be lower than 20.***&#x20;

*<mark style="background-color:red;">Each user has maximum 20MB Memory and 10 Seconds to complete all operation in function which executed.</mark>*&#x20;

*<mark style="background-color:red;">Each user has maximum 10 seconds to complete all of operation in PCse. Otherwise system will cancel current operation and point to vulnerability code blocks.</mark>*

*<mark style="background-color:red;">System needs to determine that PSce executes at least 500 times run-time to point safe PSce.</mark>*

So you can store your encrypted or none-encrypted data in the block network.&#x20;

Or&#x20;

PSce can transfer assets to other wallets if it has. **So we can say that PSce holds assets**. You can  see PSce balance list on Fig. 1.

<figure><img src="/files/4V2Ikp8wlpPAm0kpp3H5" alt=""><figcaption><p>Fig.1: PSce can hold assets.</p></figcaption></figure>


# PSce Constants

PSce uses a few of constants for helping to users that determine the PSce situations.

**EXECUTER\_ADDRESS:** PSce user's address who executes at that moment.

**OWNER\_ADDRESS:** PSce creator Address. It cannot change.

**EXECUTER\_SCENARIOADDRESS:** Current PSce Scenario Address. And Scenario Address has been created single time. It is not changable.

**AMOUNT:** Returns the number of assets sent via transaction.

**ASSETID:** Returns the asset number sent via transaction.

**EXECUTOR\_NODENAME:** Current Node Name. Explained below  code blocks how to necessary to use.

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

**ORIGINFLAG**: Origin flag constant; gives "true" value in the node that first meets the request sent by the user and "false" value in other nodes.&#x20;

So , if client sends a requests to NODE A ; \
NODE A takes "true" value at **ORIGINFLAG** other nodes takes "false" value at **ORIGINFLAG**.


# PSce Accumulator Object

PSDATA constant data Acc. Object has been stored each PSce primitive or JSON based datas. And ***we can say that Each PSce can hold its own data***.

Developers can model their needs data with PSDATA.&#x20;

```javascript
async function putScenarioBaseData(param,val)
{
    PSDATA[param]=val;
    await Map.saveMap(JSON.stringify(PSDATA));
}

 async function getScenarioBasedData(param)
{
    return PSDATA[param];
}
```

If we give an example above function

```javascript
async function init()
{
    PSDATA["myKey"]="myValue";
    await Map.saveMap(JSON.stringify(PSDATA));
    // return a transactionHash
}
async function getMyData()
{
    return PSDATA["myKey"];
    // returns "myValue";
}
```

When user execute set function ,system will start to create a new transaction to deliver other nodes.


# Simple Usage PSce

As we see below page , system generates some constants such as EXECUTER\_ADDRESS, OWNER\_ADDRESS

{% code lineNumbers="true" %}

```javascript
 async function init()
{
// Your code goes here...
 // You can execute only you 

 if (EXECUTER_ADDRESS!==OWNER_ADDRESS) 
 return "You dont have permission for execute this scenario!"; 

 var dummyTest=await Transaction.getBalance(EXECUTER_ADDRESS);
 return dummyTest;
}
```

{% endcode %}

If your address doesn't match with EXECUTER\_OWNER address , you wont execute this scenario because of **code line 6th condition**.

```javascript
 var dummyTest=await Transaction.getBalance(EXECUTER_ADDRESS);
```

When we executed above code system gives us below response;

```json
{
  "error": 0,
  "name": "PIRI",
  "symbol": "PIRI",
  "logo": "/images/piri.png",
  "assetID": -1,
  "address": "PRTMRKWZ56v4D8mV1oj813bqTgdfUm9J4woVTDMpGxF",
  "frozen": [],
  "balance": "6411.16548965"
}
```


# Generating a new transaction though PSce

PCse has capability of generating internal transactions.

**Internal Transactions (Local Transactions):** Internal Transaction (InTx) is being only generated by PCse. PCSe signaturing is made by users and PCse doesnt have right to signature any transaction. It only runs what code written. Normally any user cannot create internal transaction by using any kind of method. More descripition has been explained Fig 2.&#x20;

<figure><img src="/files/2TPe1TnwAo5R73CSYRT7" alt=""><figcaption><p>Fig 2 : Explained, how to Internal Transaction has been produced by executable transaction.</p></figcaption></figure>


# What will i have if i execute a PCse

If we have a sample PCse and we executed the depositLiqudity method ;

{% code lineNumbers="true" %}

```javascript
async function depositLiqudity(ratio)
{
    if (isNaN(ratio))
        return {error:1,message:'Ratio must be a number!'};    
    if (ratio<=0)
    return {error:1,message:'Could not set Ratio Zero or Negative Number'};
    if (AMOUNT===undefined)
        return {error:1,message:'You must send Amount!'};
    if (AMOUNT<=0)
        return {error:1,message:'Amount must be Positive!'};
    let expireDate=new Date();
    expireDate.setDate(expireDate.getDate() + 2);
    
    const addedLiqsRecords=[
        {key:'addedLiq',value:AMOUNT,enc:0},
        {key:'addedAssetID',value:ASSETID,enc:0},
        {key:'ratio',value:ratio,enc:0},
        {key:'expireDate',value:expireDate,enc:0}
    ];
    return Transaction.pushData(JSON.stringify(addedLiqsRecords),EXECUTER_ADDRESS);
}
```

{% endcode %}

System gives us below response if all conditions met. Local Transactions are made by PCse. And User must send a few of <mark style="color:red;">AMOUNT</mark>  to execute. As we see the 20th code line, PCse pushes the a new generated data into block network.

**Response:**

```json
{
  "transactionHash": "ea9cdc717dce55af99a4e2d9551fa4d546a725c247f2775ffd4fcc63c9d17e00",
  "signature": "30450221009ac12983a2337249a0a0656bc1806673e9a82049b3282e2413fb897b360aceb502200ddb7d2b0ce18305ea445a01921c8498175d9452b46d4da5dec55c32657d2be5",
  }  
```

When we call  [getTransaction method](/psce-functions/gettransaction) with relevant Transaction Hash then system gives us below **response:**

<pre class="language-json"><code class="lang-json">{
  "type": -1,
  "isFromScenario": false,
  "confirmed": true,
  "confirmationCount": 5,
  "transactionHash": "ea9cdc717dce55af99a4e2d9551fa4d546a725c247f2775ffd4fcc63c9d17e00",
  "__v": 5,
  "amount": 1000,
  "assetID": 10007,
  "blockHeight": 3919629,
  "fee": 2.3,
  "from": "PRTMRKWZ56v4D8mV1oj813bqTgdfUm9J4woVTDMpGxF",
<strong>  "metaData": "{\"type\":\"executeMethod\",\"data\":{\"scenarioAddress\":\"PRTMQbunYS1CxSs5i59CrR4ot2WUThT9JvsKvLYDfwF\",\"method\":\"depositLiqudity\",\"params\":[\"1.345678\"],\"executeAddress\":\"PRTMRKWZ56v4D8mV1oj813bqTgdfUm9J4woVTDMpGxF\"}}",
</strong>  "pub": "04489dac5311bcb1d454af5f264edf4db531f25b4c14796ff568700b8805d7e620d428a6afdc588493380fa8fa3fc88d3961940a243208730e913a0d1be738193c",
  "signature": "30450221009ac12983a2337249a0a0656bc1806673e9a82049b3282e2413fb897b360aceb502200ddb7d2b0ce18305ea445a01921c8498175d9452b46d4da5dec55c32657d2be5",
  "symbol": "PEP0",
  "timeStamp": 1704809671956,
  "to": "PRTMQbunYS1CxSs5i59CrR4ot2WUThT9JvsKvLYDfwF",
  "validatorNodes": [
    {
      "_id": "659d54c9a1901845825fb09e",
      "nodeName": "BIRUNI",
      "message": "SUCCESS",
      "dateTime": "2024-01-09T14:14:33.031Z",
      "result": 1
    },
    {
      "_id": "659d54c9a1901845825fb0a6",
      "nodeName": "INALCIK",
      "message": "SUCCESS",
      "dateTime": "2024-01-09T14:14:33.202Z",
      "result": 1
    },
    {
      "_id": "659d54c9a1901845825fb0d7",
      "nodeName": "AKURGAL",
      "message": "SUCCESS",
      "dateTime": "2024-01-09T14:14:33.487Z",
      "result": 1
    },
    {
      "_id": "659d54c9a1901845825fb0de",
      "nodeName": "CELEBI",
      "message": "SUCCESS",
      "dateTime": "2024-01-09T14:14:33.501Z",
      "result": 1
    },
    {
      "_id": "659d54c9a1901845825fb0ea",
      "nodeName": "KUSCU",
      "message": "SUCCESS",
      "dateTime": "2024-01-09T14:14:33.939Z",
      "result": 1
    }
  ],
  "customData": [],
  "broadcastHex": "007b00220070007500620022003a002200300034003400380039006400610063003500330031003100620063006200310064003400350034006100660035006600320036003400650064006600340064006200350033003100660032003500620034006300310034003700390036006600660035003600380037003000300062003800380030003500640037006500360032003000640034003200380061003600610066006400630035003800380034003900330033003800300066006100380066006100330066006300380038006400330039003600310039003400300061003200340033003200300038003700330030006500390031003300610030006400310062006500370033003800310039003300630022002c0022007300690067006e006100740075007200650022003a002200330030003400350030003200320031003000300039006100630031003200390038003300610032003300330037003200340039006100300061003000360035003600620063003100380030003600360037003300650039006100380032003000340039006200330032003800320065003200340031003300660062003800390037006200330036003000610063006500620035003000320032003000300064006400620037006400320062003000630065003100380033003000350065006100340034003500610030003100390032003100630038003400390038003100370035006400390034003500320062003400360064003400640061003500640065006300350035006300330032003600350037006400320062006500350022002c002200660072006f006d0022003a0022005000520054004d0052004b0057005a003500360076003400440038006d00560031006f006a0038003100330062007100540067006400660055006d0039004a00340077006f005600540044004d00700047007800460022002c00220074006f0022003a0022005000520054004d005100620075006e005900530031004300780053007300350069003500390043007200520034006f00740032005700550054006800540039004a00760073004b0076004c005900440066007700460022002c002200740069006d0065005300740061006d00700022003a0031003700300034003800300039003600370031003900350036002c002200610073007300650074004900440022003a00310030003000300037007d",
  "localTransactions": [
    {
      "type": 9,
      "isFromScenario": true,
      "confirmed": false,
      "confirmationCount": 0,
      "_id": "659d54f29428f9fbf0234776",
      "transactionHash": "19afc2cf0713c4710fc19ca2c53b769ca362c126ebde67cecff2f14e72f76c78",
      "__v": 0,
      "amount": 0,
      "assetID": -1,
      "blockHeight": 3919629,
      "fee": 0.3585,
      "from": "PRTMQbunYS1CxSs5i59CrR4ot2WUThT9JvsKvLYDfwF",
      "parentTransaction": "ea9cdc717dce55af99a4e2d9551fa4d546a725c247f2775ffd4fcc63c9d17e00",
      "scenarioExecuterAddress": "PRTMQbunYS1CxSs5i59CrR4ot2WUThT9JvsKvLYDfwF",
      "symbol": "PIRI",
      "timeStamp": 1704809673294,
      "to": "PRTMRKWZ56v4D8mV1oj813bqTgdfUm9J4woVTDMpGxF",
      "validatorNodes": [],
      "customDocs": [
        {
          "_id": "659d54c9a1901845825fb0c5",
          "txID": "19afc2cf0713c4710fc19ca2c53b769ca362c126ebde67cecff2f14e72f76c78",
          "key": "expireDate",
          "value": "2024-01-11T14:14:33.289Z",
          "timeStamp": 1704809673294,
          "from": "PRTMQbunYS1CxSs5i59CrR4ot2WUThT9JvsKvLYDfwF",
          "to": "PRTMRKWZ56v4D8mV1oj813bqTgdfUm9J4woVTDMpGxF",
          "enc": 0,
          "__v": 0,
          "blockHeight": 3919629
        },
        {
          "_id": "659d54c9a1901845825fb0c4",
          "txID": "19afc2cf0713c4710fc19ca2c53b769ca362c126ebde67cecff2f14e72f76c78",
          "key": "addedLiq",
          "value": "1000",
          "timeStamp": 1704809673294,
          "from": "PRTMQbunYS1CxSs5i59CrR4ot2WUThT9JvsKvLYDfwF",
          "to": "PRTMRKWZ56v4D8mV1oj813bqTgdfUm9J4woVTDMpGxF",
          "enc": 0,
          "__v": 0,
          "blockHeight": 3919629
        },
        {
          "_id": "659d54c9a1901845825fb0c6",
          "txID": "19afc2cf0713c4710fc19ca2c53b769ca362c126ebde67cecff2f14e72f76c78",
          "key": "ratio",
          "value": "1.345678",
          "timeStamp": 1704809673294,
          "from": "PRTMQbunYS1CxSs5i59CrR4ot2WUThT9JvsKvLYDfwF",
          "to": "PRTMRKWZ56v4D8mV1oj813bqTgdfUm9J4woVTDMpGxF",
          "enc": 0,
          "__v": 0,
          "blockHeight": 3919629
        },
        {
          "_id": "659d54c9a1901845825fb0c3",
          "txID": "19afc2cf0713c4710fc19ca2c53b769ca362c126ebde67cecff2f14e72f76c78",
          "key": "addedAssetID",
          "value": "10007",
          "timeStamp": 1704809673294,
          "from": "PRTMQbunYS1CxSs5i59CrR4ot2WUThT9JvsKvLYDfwF",
          "to": "PRTMRKWZ56v4D8mV1oj813bqTgdfUm9J4woVTDMpGxF",
          "enc": 0,
          "__v": 0,
          "blockHeight": 3919629
        }
      ]
    }
  ]
}
</code></pre>

It involves the metaData property explains the this transaction has been created by PCse. and we can find params and which method was executed.

```json
 "metaData": "{\"type\":\"executeMethod\",\"data\":{\"scenarioAddress\":\"PRTMQbunYS1CxSs5i59CrR4ot2WUThT9JvsKvLYDfwF\",\"method\":\"depositLiqudity\",\"params\":[\"1.345678\"],\"executeAddress\":\"PRTMRKWZ56v4D8mV1oj813bqTgdfUm9J4woVTDMpGxF\"}}",
```


# Operation Costs

Each internal transaction needs to PIRI.

Calculation of fee cares of block network bandwidth volume.&#x20;

Simple Transfer Operation,PSce execution cost described below formula;

<figure><img src="/files/zVCtk80ptghw88zBfGjk" alt="" width="270"><figcaption></figcaption></figure>

**x:** Transaction count of last approvement block.

**Execution Memory Allocation Protocol:**

In addition execution of PSce fee has a new const , that is **externally heap memory usage. It depends on your code allocation of memory at run time.**


# Double Protect!  your client assets are in safe with addition authenticator code

There is an attention for using this function! Please read carefully before operate

This is the new feature to protect your clients assets with authenticator. Learn and use are so easy. Using Authenticator Below Image explained how to model in your codes. You can use everywhere. Every secret tokens are stored under **AES encryption**. *<mark style="color:red;">**But Pirichain accepts absolutely no responsibility if you experience victimization.**</mark>*

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

As you see that below image. once you attemp to generate token. System will give you or your client a secret token and you can define your mobile phone.&#x20;

Double control with your clients assets. Even anyone knows the private key or secret phrase  , its not enough steal their assets if you code authenticator.

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

<mark style="color:orange;">**Attention: System will give 30 minutes to get Secret Token for defining the mobile authenticator Application or storing external environment.**</mark>**&#x20;&#x20;**<mark style="color:red;">**If the time exceed user cannot reach the authenticator secret token!**</mark>

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

Once you add in your phone  authenticator  application , system will give you diffenrent tokens per minutes.

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

And you can write here to validate your token in PSce.

<figure><img src="/files/30MYa5b5biQuCGX34LQc" alt=""><figcaption></figcaption></figure>

If you type wrong token system will give an error such above message. But of course all of conditions or situation depend your code.

You can investigate  this PSce in **testnet.** [**https://scanner.pirichain.com/scenario/PRTMR7HhU3fJEqrRjU9P97Qk16QQDfHKk8snGUyp6dy**](https://scanner.pirichain.com/scenario/PRTMR7HhU3fJEqrRjU9P97Qk16QQDfHKk8snGUyp6dy)


# Avoid these methods and situations in PSce

### PCse runs each node. And each node has different time period (in terms of miliseconds) if we consider milisecond time tick.

<mark style="color:blue;">So ,</mark> <mark style="color:red;">**We dont recommended**</mark> <mark style="color:blue;">that use below methods which depend on your condition</mark>

<mark style="color:blue;">**Please do not leave unused variables in PSce.**</mark>&#x20;

```
// defining V (variable)
let V={};
.
.
.
(V has not been used anywhere, it has been only defined)
```

<mark style="color:red;">**if you wont use the V variable next codes, system might be occurred an error.**</mark>

**1- Math.random()** **or depends on this** **method**&#x20;

<mark style="color:blue;">**You can use Tools.getRandom() which can generate 6 digits random number each 30 seconds.**</mark>

**2- new Date().getTime()** &#x20;

in PSce's. Because each node generates different random number and different time Ticks.


# sendPIRI

To send from PSce to other defined address.

{% code overflow="wrap" lineNumbers="true" %}

```javascript
const result = await Transaction.sendPIRI(<Receipt Address:Base58>,<amount:integer | float>);
```

{% endcode %}

**Sample :**&#x20;

```javascript
const result = await Transaction.sendPIRI('PRTMPp6wo6zGAcStmhmBGQErnomzhFCoaTfLuXKTvo2',100.999);
```

This is special method , similar to [sendToken](/psce-functions/sendtoken) function but there is no need assetID. System created a new internal transaction when code line 1 executed.

Response:

```json
{
    "executedResult":{},
    "error":0,
    "tx":"a3449d13cc98521e2711f4f033d99f93876c507739774986e08f0574a89e7d9d",
    "sign":"3045022054d25f4efa52bcf785588c5ad49f60d06955f01476a7de41bd5c6a4893d980e1022100d214cb6a377813b392847532ebaa85bc7f7ca9d99ab12003be5471471e3b3a7d",
    "timeStamp":1705185353375
}
```


# sendToken

To send from PSce to other defined address.

{% code overflow="wrap" lineNumbers="true" %}

```javascript
const result = await Transaction.sendToken(<Receipt Address:Base58>,<amount:integer | float >, <assetID:integer>);
```

{% endcode %}

System creates a new internal transaction which has type 9 when above code executed. So Type 9 transactions cannot move to other nodes. Because Only moving transactions type are -1. We described this point on      [this page](/generating-a-new-transaction-though-psce).

**Example:**

{% code overflow="wrap" lineNumbers="true" %}

```javascript
const result = await Transaction.sendToken('PRTMPp6wo6zGAcStmhmBGQErnomzhFCoaTfLuXKTvo2',10.1, -1);
```

{% endcode %}

As we see above sample, first parameter PIRI Address that must be match PIRI Address strandarts. 2nd parameter amount ,3rd assetID (PIRI coin asset ID :-1)

**Response:**

```json
{
    "executedResult":{},
    "error":0,
    "tx":"a1149d13cc98521e2711f4f033d99f93876c507739774986e08f0574a89e7d9d",
    "sign":"3045022054d25f4efa52bcf78558854ad49f60d06955f01476a7de41bd5c6a4893d980e1022100d214cb6a377813b392847532ebaa85bc7f7ca9d99ab12003be5471471e3b3a7d",
    "timeStamp":1705185399375
}
```


# pushData

pushData Method allows to store customized data pattern in blocknetwork

```javascript
  const result=await Transaction.pushData(<MyObjectStringFormat:string>,<address:Base58>);
```

It has been syntax usage explained above. And we can make a sample below.

```javascript
const myData=[
                {key:'myKey1',value:'myValue Data',enc:0},
                {key:'myKey2',value:'myValue Data2',enc:0},
                {key:'myKey3',value:'mySecretValue',enc:1},
                {key:'mySecretKey',value:'mySecretValue2',enc:2}
                ];
                
const result=await Transaction.pushData(JSON.stringify(myData),<address>);
```

As we see that above sample. user can store an array in Pirichain network though PCse.

:information\_source:**key :** Define a identification property,

:information\_source:**value :** Define a providing value in your model.

:information\_source: **enc** : Encryption Level \
[0: Non-Encrypted\
1: Only Value Encrypted\
2: Key And Value Encrypted](#user-content-fn-1)[^1]

**Response :**

```json
{
    "executedResult":{},
    "error":0,
    "tx":"a3449d13cc98521e2711f4f033d99f93876c507739774986e08f0574a89e7d9d",
    "sign":"3045022054d25f4efa52bcf785588c5ad49f60d06955f01476a7de41bd5c6a4893d980e1022100d214cb6a377813b392847532ebaa85bc7f7ca9d99ab12003be5471471e3b3a7d",
    "timeStamp":1705185353375
}
```

[^1]:


# getBalance

To get latest balance relevant address

{% code overflow="wrap" lineNumbers="true" %}

```javascript
const result = await Transaction.getBalance(<Receipt Address:Base58>,<assetID:integer>);
```

{% endcode %}

To get latest wallet balance info, we can use above methods&#x20;

Sample:&#x20;

```javascript
const result = await Transaction.getBalance('PRTMPp6wo6zGAcStmhmBGQErnomzhFCoaTfLuXKTvo2',-1);
```

Response Example:

```json
{
    "error":0,
    "name":"PIRI",
    "symbol":"PIRI",
    "logo":"/images/piri.png",
    "assetID":-1,
    "address":"PRTMRKWZ56v4D8mV1oj813bqTgdfUm9J4woVTDMpGxF",
    "frozen":[{"_id":null,"totalFrozen":216000.9}],
    "balance":"348782.10281186"
}
```


# getBalanceList

To get balance List of relevant address

{% code overflow="wrap" lineNumbers="true" %}

```javascript
const result = await Transaction.getBalanceList(<Receipt Address:Base58>);
```

{% endcode %}

To get latest wallet balance info, we can use above methods.

**Sample:**&#x20;

```javascript
const result = await Transaction.getBalanceList('PRTMPp6wo6zGAcStmhmBGQErnomzhFCoaTfLuXKTvo2');
```

**Response Example:**

```json
[
    {
    "error":0,
    "name":"PIRI",
    "symbol":"PIRI",
    "logo":"/images/piri.png",
    "assetID":-1,
    "address":"PRTMR5sqPyVKHjeHMZkAqKx7AjJGmwdhUkx8aj7PdCn",
    "frozen":[],
    "balance":"0.00000000"
    }
]
```


# getPureTransaction

Getting simple tx record though Transaction Hash.

{% code overflow="wrap" lineNumbers="true" %}

```javascript
const result = await Transaction.getPureTransaction(<TransactionHash:HexString>);
```

{% endcode %}

To get simple transaction infos using with above method.

**Sample:**&#x20;

```javascript
const result = await Transaction.getPureTransaction('fc837a22143456eba77b0637b2454f18434298b52bb376fda8a8021edc133de9');
```

Response Example:

```json
{
    "type":-1,
    "isFromScenario":false,
    "transactionHash":"fc837a22143456eba77b0637b2454f18434298b52bb376fda8a8021edc133de9","
    amount":0,
    "assetID":-1,
    "blockHeight":3957190,
    "fee":0.2575,
    "from":"PRTMPLGiRmUVuiaCcdFudXebEEDa4o2u61vGM3PbHZK",
    "pub":"0489981e828063c4f71c726920c96241cd969a5189574af9b75729c56f9e4c7e94b3c74ce825ecd9652b2d7871379b6c1790b3f96d342b504b85583c119ab9a08b",
    "signature":"3045022100a28e8bf084313fa17e3ddd136b15cd89c071c9ab2d5706ed9bfe9f0ead72411d02203bf8ba6a611aba55aae18c9c694b3905dc3473fcfe5de1ecdf5946e037c68b4b",
    "symbol":"PIRI",
    "timeStamp":1705185310589,
    "to":"PRTMRGAZ9XChpq32APAKbTiYZpeUiA3ZrP1PPuq48pR"
}
```


# getTransaction

Getting detailed tx record though Transaction Hash.

{% code overflow="wrap" lineNumbers="true" %}

```javascript
const result = await Transaction.getTransaction(<TransactionHash:HexString>);
```

{% endcode %}

To get detailed transaction infos using with above method.

**Sample:**

```javascript
const result = await Transaction.getTransaction('fc837a22143456eba77b0637b2454f18434298b52bb376fda8a8021edc133de9');
```

Response Example:

```json
{
    "type":-1,
    "isFromScenario":false,
    "transactionHash":"fc837a22143456eba77b0637b2454f18434298b52bb376fda8a8021edc133de9","
    amount":0,
    "assetID":-1,
    "blockHeight":3957190,
    "fee":0.2575,
    "from":"PRTMPLGiRmUVuiaCcdFudXebEEDa4o2u61vGM3PbHZK",
    "pub":"0489981e828063c4f71c726920c96241cd969a5189574af9b75729c56f9e4c7e94b3c74ce825ecd9652b2d7871379b6c1790b3f96d342b504b85583c119ab9a08b",
    "signature":"3045022100a28e8bf084313fa17e3ddd136b15cd89c071c9ab2d5706ed9bfe9f0ead72411d02203bf8ba6a611aba55aae18c9c694b3905dc3473fcfe5de1ecdf5946e037c68b4b",
    "symbol":"PIRI",
    "timeStamp":1705185310589,
    "to":"PRTMRGAZ9XChpq32APAKbTiYZpeUiA3ZrP1PPuq48pR"
}
```


# listPoolTransactions

Getting detailed tx record though Transaction Hash.

{% code lineNumbers="true" %}

```javascript
const result = await Transaction.listPoolTransactions();
```

{% endcode %}

To get detailed transaction infos using with above method.

**Sample:**

```javascript
const result = await Transaction.listPoolTransactions();
```

Response Example:

```json
[{
    "type":-1,
    "isFromScenario":false,
    "transactionHash":"fc837a22143456eba77b0637b2454f18434298b52bb376fda8a8021edc133de9","
    amount":0,
    "assetID":-1,
    "blockHeight":3957190,
    "fee":0.2575,
    "from":"PRTMPLGiRmUVuiaCcdFudXebEEDa4o2u61vGM3PbHZK",
    "pub":"0489981e828063c4f71c726920c96241cd969a5189574af9b75729c56f9e4c7e94b3c74ce825ecd9652b2d7871379b6c1790b3f96d342b504b85583c119ab9a08b",
    "signature":"3045022100a28e8bf084313fa17e3ddd136b15cd89c071c9ab2d5706ed9bfe9f0ead72411d02203bf8ba6a611aba55aae18c9c694b3905dc3473fcfe5de1ecdf5946e037c68b4b",
    "symbol":"PIRI",
    "timeStamp":1705185310589,
    "to":"PRTMRGAZ9XChpq32APAKbTiYZpeUiA3ZrP1PPuq48pR"
}
]
```


# findData

You can use this command to find data which has been saved block network.

```javascript
const result = await Transaction.findData(<Address:Base58>,<key:string>,<skip:integer>,<limit:integer>)

```

**Address:**  Get data from saved to this Pirichain wallet address before.

**Key:** Get data by key property&#x20;

**Skip :** Skip Relevant data records

**Limit:** Set limitation of records

**Sample :**

{% code overflow="wrap" %}

```javascript
const result=await Transaction.findData('PRTMQbunYS1CxSs5i59CrR4ot2WUThT9JvsKvLYDfwF','ratio',0,100);
```

{% endcode %}

System will get **data array** which include "ratio" key which stored same transaction. As we see that below response, system returned 4 different transaction that have **ratio** **key**.

**Response:**

```json
[
    {"addedAssetID":"10007","addedLiq":"100","expireDate":"2024-01-20T10:49:58.396Z","ratio":"1.2"},
    // tx1
    {"addedLiq":"10","expireDate":"2024-01 15T22:35:54.143Z","addedAssetID":"10007","ratio":"1.112"}, 
    //tx2
    {"addedAssetID":"10007","expireDate":"2024-01-14T12:24:24.492Z","ratio":"1.112","addedLiq":"19"},
    //tx3
    {"addedAssetID":"10007","expireDate":"2024-01-14T12:24:24.040Z","addedLiq":"19","ratio":"1.112"}
    //tx4
]
```


# findDataWithAddress

You can use this command to find data which has been saved block network.

```javascript
const result = await Transaction.findDataWithAddress(<from:Base58>, <to:Base58>, <key:string>, <skip:integer>, <limit:integer>)

```

**From:**  Sender Address

**To:** Receipt Address

**Key:** Get data by key property&#x20;

**Skip :** Skip Relevant data records

**Limit:** Set limitation of records

**Sample:**

{% code overflow="wrap" %}

```javascript
return Transaction.findDataWithAddress('PRTMQbunYS1CxSs5i59CrR4ot2WUThT9JvsKvLYDfwF','PRTMRAwXEVfbTD7bsYgkP74JFuKtPZ6hDcXxMWQKpEJ','ratio',0,100);
```

{% endcode %}

System will get **data array** which include "ratio" key which stored same transaction. As we see that below response, system returned 4 different transaction that have **ratio** **key**.

**Response:**

```json
[
    {"addedAssetID":"10007","addedLiq":"100","expireDate":"2024-01-20T10:49:58.396Z","ratio":"1.2"},
    // tx1
    {"addedLiq":"10","expireDate":"2024-01 15T22:35:54.143Z","addedAssetID":"10007","ratio":"1.112"}, 
    //tx2
    {"addedAssetID":"10007","expireDate":"2024-01-14T12:24:24.492Z","ratio":"1.112","addedLiq":"19"},
    //tx3
    {"addedAssetID":"10007","expireDate":"2024-01-14T12:24:24.040Z","addedLiq":"19","ratio":"1.112"}
    //tx4
]
```


# findDataWithValue

You can use this command to find data which has been saved block network.

```javascript
const result = await Transaction.findDataWithValue(<address:Base58>, <key:string>, <value:string>, <skip:integer>, <limit:integer>)

```

**From:**  Sender Address

**To:** Receipt Address

**Key:** Get data by key property&#x20;

**Value:** Get data by value property

**Skip :** Skip Relevant data records

**Limit:** Set limitation of records

**Sample :**&#x20;

{% code overflow="wrap" %}

```javascript
return Transaction.findDataWithValue('PRTMQbunYS1CxSs5i59CrR4ot2WUThT9JvsKvLYDfwF','ratio','1.2',0,100);
```

{% endcode %}

**Response:**

```json
[
    {"addedAssetID":"10007",
     "addedLiq":"100",
     "expireDate":"2024-01-20T10:49:58.396Z",
     "ratio":"1.2"}
]
```


# findDataUpperThanValue

You can use this command to find data which has been saved block network.

```javascript
const result = await Transaction.findDataUpperThanValue(<from:Base58>, <to:Base58>, <key:string>,<value:float|integer>, <skip:integer>, <limit:integer>)

```

**From:**  Sender Address

**To:** Receipt Address

**Key:** Get data by key property ,

**Value:** Get data by value propert, must be float or integer

**Skip :** Skip Relevant data records

**Limit:** Set limitation of records

**Sample:**

```javascript
const result = await Transaction.findDataUpperThanValue(<from:Base58>, <to:Base58>, <key:string>,<value:float|integer>, <skip:integer>, <limit:integer>)
```

**Response:**

```json
[
    {
        "myKey":"Thats my value!"
    }
]
```


# findDataLowerThanValue

You can use this command to find data which has been saved block network.

```javascript
const result = await Transaction.findDataLowerThanValue(<from:Base58>, <to:Base58>, <key:string>,<value:float|integer>, <skip:integer>, <limit:integer>)

```

**From:**  Sender Address

**To:** Receipt Address

**Key:** Get data by key property ,

**Value:** Get data by value propert, must be float or integer

**Skip :** Skip Relevant data records

**Limit:** Set limitation of records

**Response:**

```json
[
    {
        "myKey":"Thats my value!"
    }
]
```


# getRandom

make a new randomized number and all nodes will give same  six digit number.

getRandom function depends to your network ROF (Random Optimization Factor) where defined in HAN.JSON file.

```javascript
return await Tools.getRandom();
// Response : 998334
```


# getData

Allows get data from external environments

```javascript
const externalResult=await Transaction.getData(<url:string>);
```

This method provides to get data from external environments.

**Sample:**

```javascript
const allCoffee=await Tools.getData("https://api.sampleapis.com/coffee/hot");
```

**Response:**

```json
{
 "error": 0,
 "data": [
  {
   "title": "Black Coffee",
   "description": "Svart kaffe är så enkelt som det kan bli med malda kaffebönor dränkta i hett vatten, serverat varmt. Och om du vill låta fancy kan du kalla svart kaffe med sitt rätta namn: café noir.",
   "ingredients": [
    "Coffee"
   ],
   "image": "https://images.unsplash.com/photo-1494314671902-399b18174975?auto=format&fit=crop&q=80&w=1887&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
   "id": 1
  },
  {
   "title": "Latte",
   "description": "Som den mest populära kaffedrycken där ute består latte av en skvätt espresso och ångad mjölk med bara en gnutta skum. Den kan beställas utan smak eller med smak av allt från vanilj till pumpa kryddor.",
   "ingredients": [
    "Espresso",
    "Ångad mjölk"
   ],
   "image": "https://images.unsplash.com/photo-1561882468-9110e03e0f78?auto=format&fit=crop&q=60&w=800&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTl8fGxhdHRlfGVufDB8fDB8fHww",
   "id": 2
  },
  {
   "title": "Caramel Latte",
   "description": "Om du gillar latte med en speciell smak kan karamell latte vara det bästa alternativet för att ge dig en upplevelse av den naturliga sötman och krämigheten hos ångad mjölk och karamell.",
   "ingredients": [
    "Espresso",
    "Ångad mjölk",
    "Karamellsirap"
   ],
   "image": "https://images.unsplash.com/photo-1599398054066-846f28917f38?auto=format&fit=crop&q=80&w=1887&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
   "id": 3
  },
  {
   "title": "Cappuccino",
   "description": "Cappuccino är en latte som är gjord med mer skum än ångad mjölk, ofta med ett strö av kakaopulver eller kanel på toppen. Ibland kan du hitta variationer som använder grädde istället för mjölk eller sådana som tillsätter smakämnen också.",
   "ingredients": [
    "Espresso",
    "Ångad mjölk",
    "Foam"
   ],
   "image": "https://images.unsplash.com/photo-1557006021-b85faa2bc5e2?auto=format&fit=crop&q=80&w=1887&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
   "id": 4
  },
  {
   "title": "Americano",
   "description": "Med en liknande smak som svart kaffe består americano av en espresso skott utspätt med hett vatten.",
   "ingredients": [
    "Espresso",
    "Hett vatten"
   ],
   "image": "https://images.unsplash.com/photo-1532004491497-ba35c367d634?auto=format&fit=crop&q=80&w=1887&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
   "id": 5
  },
  {
   "title": "Espresso",
   "description": "Ett espressoskott kan serveras ensamt eller användas som grund för de flesta kaffedrycker, som latte och macchiato.",
   "ingredients": [
    "Espresso"
   ],
   "image": "https://images.unsplash.com/photo-1579992357154-faf4bde95b3d?auto=format&fit=crop&q=80&w=1887&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
   "id": 6
  },
  {
   "title": "Macchiato",
   "description": "Macchiaton är en annan espresso-baserad dryck som har en liten mängd skum på toppen. Det är det glada mellanrummet mellan en cappuccino och en doppio.",
   "ingredients": [
    "Espresso",
    "Foam"
   ],
   "image": "https://images.unsplash.com/photo-1557772611-722dabe20327?auto=format&fit=crop&q=80&w=1887&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
   "id": 7
  },
  {
   "title": "Mocha",
   "description": "För alla chokladälskare där ute kommer ni att bli förälskade i en mocha. Mocha är en choklad-espressodryck med ångad mjölk och skum.",
   "ingredients": [
    "Espresso",
    "Ångad mjölk",
    "Choklad"
   ],
   "image": "https://images.unsplash.com/photo-1607260550778-aa9d29444ce1?auto=format&fit=crop&q=80&w=1887&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
   "id": 8
  },
  {
   "title": "Hot Chocolate",
   "description": "Under kalla vinterdagar får en kopp varm choklad dig att känna dig bekväm och lycklig. Den får dig också att må bra eftersom den innehåller energigivande koffein.",
   "ingredients": [
    "Choklad",
    "Mjölk"
   ],
   "image": "https://images.unsplash.com/photo-1542990253-0d0f5be5f0ed?auto=format&fit=crop&q=60&w=800&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NDh8fGhvdCUyMGNob2NvbGF0ZXxlbnwwfHwwfHx8MA%3D%3D",
   "id": 9
  },
  {
   "title": "Chai Latte",
   "description": "Om du letar efter en smakfull varm dryck mitt i vintern, välj chai latte. Kombinationen av kardemumma och kanel ger en underbar smak.",
   "ingredients": [
    "Te",
    "Mjölk",
    "Ingefära",
    "Kardemumma",
    "Kanel"
   ],
   "image": "https://images.unsplash.com/photo-1578899952107-9c390f1af1b7?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTJ8fGNoYWklMjBsYXR0ZXxlbnwwfHwwfHx8MA%3D%3D",
   "id": 10
  },
  {
   "title": "Matcha Latte",
   "description": "Matcha latte är en grön, hälsosam kaffedryck med finkrossad matcha-te och mjölk, erbjuder mild sötma, en unik smak och en mild koffeinkick.",
   "ingredients": [
    "Matcha-pulver",
    "Mjölk",
    "Socker*"
   ],
   "image": "https://images.unsplash.com/photo-1536256263959-770b48d82b0a?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8M3x8bWF0Y2hhJTIwbGF0dGV8ZW58MHx8MHx8fDA%3D",
   "id": 11
  },
  {
   "title": "Seasonal Brew",
   "description": "Säsongs kaffe med olika smaktoner som karamell, frukt och choklad",
   "ingredients": [
    "Kaffe"
   ],
   "image": "https://images.unsplash.com/photo-1611162458324-aae1eb4129a4?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTg1fHxibGFjayUyMGNvZmZlZXxlbnwwfHwwfHx8MA%3D%3D",
   "id": 12
  },
  {
   "title": "Svart Te",
   "description": "Svart te föddes i Kina. Det är tillverkat av blad från en växt som kallas Camellia och kan smaksättas olika med frukter till exempel. En trevlig, varm, smakfull och aromatisk dryck som passar till vardagen.",
   "ingredients": [
    "Te"
   ],
   "image": "https://images.unsplash.com/photo-1576092768241-dec231879fc3?auto=format&fit=crop&q=60&w=800&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MjB8fHRlYXxlbnwwfHwwfHx8MA%3D%3D",
   "id": 13
  },
  {
   "title": "Islatte",
   "description": "Iced latte är en kyld kaffedryck som görs genom att blanda espresso och kyld mjölk. Den serveras med isbitar och är även känd som cafè latte iced eller latte on the rocks.",
   "ingredients": [
    "Espresso",
    "Mjölk",
    "Is",
    "Sirap"
   ],
   "image": "https://images.unsplash.com/photo-1517701550927-30cf4ba1dba5?auto=format&fit=crop&q=60&w=800&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NHx8aWNlZCUyMGxhdHRlfGVufDB8fDB8fHww",
   "id": 14
  },
  {
   "title": "Islatte Mocha",
   "description": "Iced latte Mocha är en kombination av latte och mocha, som i sig är en kombination av choklad och kaffe. Den ger kalla dryckälskare en läcker upplevelse av choklad och kaffe.",
   "ingredients": [
    "Espresso",
    "Is",
    "Mjölk",
    "Choklad "
   ],
   "image": "https://images.unsplash.com/photo-1642647391072-6a2416f048e5?auto=format&fit=crop&q=60&w=800&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mzh8fGljZWQlMjBtb2NoYSUyMGxhdHRlfGVufDB8fDB8fHww",
   "id": 15
  },
  {
   "title": "Frapino Caramel",
   "description": "Det är en blandad eller bättre sagt skakad kaffe med vispad grädde på toppen. Ett måste för varma sommardagar.",
   "ingredients": [
    "coffee",
    "Is",
    "Mjölk",
    "Karamellsirap",
    "Vispgrädde*",
    "Karamellsås"
   ],
   "image": "https://images.unsplash.com/photo-1662047102608-a6f2e492411f?auto=format&fit=crop&q=60&w=800&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NHx8ZnJhcGlubyUyMGNhcmFtZWx8ZW58MHx8MHx8fDA%3D",
   "id": 16
  },
  {
   "title": "Frapino Mocka",
   "description": "Ännu en berömd och utsökt kall dryck för dem som föredrar choklad. Tänk dig smaken av en shake med choklad och vispad grädde på toppen.",
   "ingredients": [
    "Coffee",
    "Is",
    "Mjölk",
    "Cocoa",
    "Vispgrädde*"
   ],
   "image": "https://images.unsplash.com/photo-1530373239216-42518e6b4063?auto=format&fit=crop&q=60&w=800&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NHx8ZnJhcGlubyUyMG1vY2hhfGVufDB8fDB8fHww",
   "id": 17
  },
  {
   "title": "Apelsinjuice",
   "description": "Vi har inget att säga om vår nypressade apelsinjuice. Du måste prova den själv.",
   "ingredients": [
    "Färska Apelsiner",
    "Is"
   ],
   "image": "https://images.unsplash.com/photo-1600271886742-f049cd451bba?auto=format&fit=crop&q=60&w=800&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NzF8fG9yYW5nZSUyMGp1aWNlfGVufDB8fDB8fHww",
   "id": 18
  },
  {
   "title": "Frozen Lemonade",
   "description": "Frozen lemonade är en uppfriskande sommardryck som kombinerar färskpressad citronsaft, is och sötning till en svalkande, syrlig och sötsyrlig smaksensation.",
   "ingredients": [
    "Citronsaft",
    "Is",
    "Socker*"
   ],
   "image": "https://images.unsplash.com/photo-1523371054106-bbf80586c38c?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTZ8fGxlbW9uYWRlJTIwd2l0aCUyMGljZXxlbnwwfHwwfHx8MA%3D%3D",
   "id": 19
  },
  {
   "title": "Lemonad",
   "description": "Var känd i Paris först och blev sedan mycket populär i hela Europa. Denna söta, färglösa, kolsyrade dryck görs genom att blanda citronsaft och kolsyrat vatten.",
   "ingredients": [
    "Citronsaft",
    "Kolsyrat vatten",
    "Honung"
   ],
   "image": "https://images.unsplash.com/photo-1621263764928-df1444c5e859?auto=format&fit=crop&q=60&w=800&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Nnx8bGVtb25hZGV8ZW58MHx8MHx8fDA%3D",
   "id": 20
  }
 ]
}
```

```javascript
```


# postData

Allows get data from external environments

```javascript
const externalResult=await Transaction.postData(<url:string>,<dataBody:string>,<options:string>);
```

This method provides to post data to external environments.

**Sample:**

```javascript
const dataBody={name:'myname',surname:'mySurname'};

const allCoffee=await Tools.postData("https://api.sampleapis.com/coffee/hot",
JSON.stringify(dataBody));
```

**Response:**

```json
{
    result:1,
    message:'Your Request has been proceed'
}
```


# generateAuthenticator

Allow to generate a new secret token each wallet.

```javascript
const transactionResult= await Tools.generateAuthenticator();
```

Above code provides to create a new protection factor with clients assets. You can model to add authenticator factor and hackers cannot access the wallet to transfer , even if they know the private key!

**Response:**

```
{
    "executedResult":{},
    "error":0,
    "tx":"a3449d13cc98521e2711f4f033d99f93876c507739774986e08f0574a89e7d9d",
    "sign":"3045022054d25f4efa52bcf785588c5ad49f60d06955f01476a7de41bd5c6a4893d980e1022100d214cb6a377813b392847532ebaa85bc7f7ca9d99ab12003be5471471e3b3a7d",
    "timeStamp":1705185353375
}
```


# verifyAuthenticator

Allow to generate a new secret token each wallet.

```javascript
const transactionResult= await Tools.verifyAuthenticator(<token:string>);
```

This code checks secret code and token which taken from mobile phone authenticator. If its verified then system will give you Boolean value (true /false).

**Response:**

```
true / false
```


# getMyAuthenticatorToken

Allow to generate a new secret token each wallet.

```javascript
const transactionResult= await Tools.getMyAuthenticatorToken();
```

This code gives relevant wallet secret token to use  at the mobile application.

**Response:**

{% code overflow="wrap" %}

```
{"error":0,"mySecretToken":"HI3HQYTJLZWQYVC5IVKCIY2GN5SECPZ6","message":"Please keep it  in safe this secret Token and define your phone Authenticator Application and you cannot reach out this  secret token after 30 minutes!"}
```

{% endcode %}


# Validators

PSce helps to determine data types under methods

{% code lineNumbers="true" %}

```javascript
  Validator.isNumeric(str:string):bool
 
  Validator.isMail(str:string):bool
 
  Validator.isHex(str:string):bool
 
  Validator.isBase64(str:string):bool
 
  Validator.isBase32(str:string):bool
 
  Validator.isMACAddress(str:string):bool
 
  Validator.isOctal(str:string):bool
 
  Validator.isJSON(str:string):bool
 
  Validator.isStrongPassword(str:string):bool
 
  Validator.isAscii(str:string):bool
 
  Validator.isIP(str:string):bool
 
```

{% endcode %}

**Example**\`\`\`javascript

```javascript
if ((await Validator.isNumeric("1234"))==false)
    return {error:1,message:'Its Not A Numeric!'};
else
    return {error:0};
```

```javascript
When the above codes executed  Screen returns 
{error:0}
```


# Examples


# Get PSce owner wallet balance

Detection Authorization of PSce wallet.

```javascript
 async function init(param1,param2,param3)
{

// A restriction of using this function only can be execute PSce owner wallet.
 if (EXECUTER_ADDRESS!==OWNER_ADDRESS) 
 return "You dont have permission for execute this scenario!"; 


 var dummyTest=await Transaction.getBalance(EXECUTER_ADDRESS);
 // EXECUTER_ADDRESS (who executes this PSce) get balance
 return dummyTest;
 // return the balance
}
```


# sendToken Example

A sample usage for sending token from PSce to defined address.

The most important thing is sender address will be Smart Scenario Address. So you can send your token or PIRI to PSce. **You cannot send your assets to receipt wallet address though PSce.**&#x20;

**You can send your token or PIRI to PSce** and **PSce will send your defined address wallet depends on your code.**

Below code lines explained that Pirichain Smart Scenario is sending a token (which belong asset ID 10001)  to your defined wallet address.

```javascript
 async function init(param1,param2,param3)
{
 var dummyTest=await Transaction.sendToken('PRTMRPqsxkGGCQ7UE9s6TZ4iNC4cM2Qa1mvCS8Unehv',0.1,10001)
 return dummyTest;
}
```


# EVM based similar approach-  Token Management With PSDATA

Manage a simple token management in PSce very easily.

*<mark style="color:red;">**Attention! , Below code lines are only sample. And Pirichain has more powerful token management using with**</mark>* [*<mark style="color:red;">**sendToken**</mark>*](/psce-functions/sendtoken) *<mark style="color:red;">**or**</mark>* [*<mark style="color:red;">**sendPIRI**</mark>*](/psce-functions/sendpiri) *<mark style="color:red;">**functions. If you want to create a new token which used under code lines , its up your decision. But commission might be more than classic sendToken and sendPIRI functions.**</mark>*

*<mark style="color:red;">**Accumulator can serve many of different conditions and situations that you can use.**</mark>*

{% code lineNumbers="true" %}

```javascript
const myTokenName="WhateverTokenName";
const tokenTotalSupply=10000000;
const decimal=18;

async function transfer(to,amount)
{
    if (isNaN(parseFloat(amount)) || parseFloat(amount)<=0)
        return {error:1,message:'Amount cannot be wrong format or negative or zero!'};
    
    
    let myBalance=PSDATA[EXECUTER_ADDRESS];
    if (myBalance!==undefined)
    {
        if (!isNaN(parseFloat(myBalance)))
        {
            myBalance=parseFloat(myBalance);
            if (parseFloat(myBalance)-parseFloat(amount)<0)
            {
                return {error:1,message:'Insufficent Balance '+myTokenName};
            }
            else
            {
                let receiptBalance=PSDATA[to];
                if (receiptBalance===undefined)
                    receiptBalance=0;
                    receiptBalance+=parseFloat(amount);
                    
                PSDATA[to]=receiptBalance;
                PSDATA[EXECUTER_ADDRESS]-=parseFloat(amount);
                return await Map.saveMap(JSON.stringify(PSDATA));
                
            }
        }
        else return {error:1,message:'Balance is not true format!'};
    }
    else
        return {error:1,message:'Insufficent Balance '+myTokenName};
}

async function mint(mintAmount)
{
    if (isNaN(parseFloat(mintAmount)) || parseFloat(mintAmount)<=0)
        return {error:1,message:'mintAmount cannot be wrong format or negative or zero!'};
    
    if (EXECUTER_ADDRESS!=OWNER_ADDRESS)
        return {error:1,message:'This function can only be executed by Scenario Owner!'}
    else
    {
        let totalMint=PSDATA['totalMinted']==undefined?0:parseFloat(PSDATA['totalMinted']);
        totalMint+=mintAmount;
        
        if (totalMint>=tokenTotalSupply)
            return {error:1,message:'Total mint cannot be increased!'};
        else
        {
             let ownerBalance=PSDATA[OWNER_ADDRESS]==undefined
             ?
             0
             :
             parseFloat(PSDATA[OWNER_ADDRESS]);
             
             ownerBalance+=mintAmount;
             PSDATA['totalMinted']=totalMint;
             PSDATA[OWNER_ADDRESS]=ownerBalance;
             return await Map.saveMap(JSON.stringify(PSDATA));

        }
    }
}
async function listTokenTransactions(skip,limit)
{
    return await Transaction.listTransactions(EXECUTER_SCENARIOADDRESS,skip,limit);

}
async function getBalance(address)
{
    return PSDATA[address]===undefined
    ?
    0
    :
    PSDATA[address];
}

async function getBalanceExecuter()
{
    return getBalance(EXECUTER_ADDRESS);
}

async function getBalance(address)
{
    return PSDATA[address]===undefined
    ?
    0
    :
    PSDATA[address];
}
async function getCirculationSupply()
{
    return PSDATA['totalMinted']==undefined?0:PSDATA['totalMinted'];
}
async function getTokenName()
{
    return myTokenName;
}
async function getTotalSupply()
{
    return tokenTotalSupply;
}
async function getDecimal()
{
    return decimal;
}
```

{% endcode %}


# Connect to EXTERNAL ENVIRONMENTS!

As you can see that below code is able to connect for getting data from external environments. **The important thing is system will need to fetch at least 11 different nodes defined endpoint url.**

{% code lineNumbers="true" %}

```javascript
 async function init(typeOfCoffee)
{
const allCoffee=await Tools.getData("https://api.sampleapis.com/coffee/hot");

//return allCoffee;
        if (allCoffee)
        {
            if (Array.isArray(allCoffee.data))
            {

                for (let i=0;i<allCoffee.data.length;i++)
                    if (allCoffee.data[i].title===typeOfCoffee)
                    {
                        return "You choosed Title :"+allCoffee.data[i].title+
                        " This Item Description : "+
                        allCoffee.data[i].description;
                    }
            }
        }
        return "You defined title , Not found!";
}
```

{% endcode %}


# Time Based Inheritor Example

TimeStamp variable defined at line 10th. And comparing to timeStamp with **server time value** on 11th code line.

{% code overflow="wrap" lineNumbers="true" %}

```javascript
async function init()
{

    const inheritorAddress="PRTMRPqsxkGGCQ7UE9s6TZ4iNC4cM2Qa1mvCS8Unehv";
    const annoucementUrl='https://mydomain.com/APIUrl';

    if (EXECUTER_ADDRESS!==inheritorAddress) 
       return {error:1,data:'The scenario is only executed by Inheritor Address'}; 

        const time_01_01_2035_0_0_0=2051222400000; // Starting to operate in 01/01/2035 
        if (new Date().getTime()>time_01_01_2035_0_0_0)
        {
            const all_Balance_This_Wallet=Transaction.getBalance(EXECUTER_SCENARIOADDRESS);
            let willBeSended=all_Balance_This_Wallet.balance-0.1; // subtracted fee cost;
            let result=await Transaction.sendPIRI(inheritorAddress,willBeSended);
            if (result.error==0)
            {
            return await Tools.postData( // Sending data to outer from Pirichain Platform...
                annoucementUrl,
                {inheritorAddress:inheritorAddress,
                operation:true
                });
            }
            else
            return {error:1,data:result.data};

        }
        else
        return {error:1,data:'Time of inheritance has not been occurred yet.'+
        ' Please Wait 01/01/2035.'}
 
}
```

{% endcode %}


# Token Example with Ticket Operation

```javascript
//####PIRICHAIN Smart Scenario v.1.0########
// TICKET Token Sample Scenario

// System first fetches data from external environment , 
//checks the received data where is real or fake user infos
//and then
// controls to send one TICKET Token to users and cut 10 PIRI coin for each TICKET.

 async function TryToBuyTicket(name,surname)
{
    // Checking Amount Price
    if (parseInt(AMOUNT)<10 )
        return {error:1,message:'You must send 10 PIRI Coin for buy ticket!'};

    const userPiriBalance=await Transaction.getBalance(EXECUTER_ADDRESS,-1);

    if (parseFloat(userPiriBalance.balance)<10)
       return {error:1,message:'You dont have enough Piri Coin to buy ticket!'};

    let result=await Tools.getData('https://dummyjson.com/users');
    if (!result) return {error:1,message:'Result Object not fetched!'};
    if (!result.data) return {error:1,message:'Result Data not fetched!'};
    if (!result.data.users) return {error:1,message:'Users not fetched!'};
    try
    {
        var user=result.data.users.find((user)=> 
                        user.firstName==name 
                        && user.lastName==surname);
        if (user)
        {
            const isUserBoughtBeforeTicket=await Transaction.getBalance(EXECUTER_ADDRESS,10006);
            if (parseInt(isUserBoughtBeforeTicket.balance)==0)
            {
                // Send to Ticket Revelant Address
                const transactionResult=await Transaction.sendToken(EXECUTER_ADDRESS,1,10006);
                if (transactionResult.tx)
                {
                    // Inform to ticket organizator using with their service 
                    //for completed new ticket operation
                    await Tools.postData('https://ticketorganizatorservice.xyz/newTicket/',{tx:transactionResult.tx,address:EXECUTER_ADDRESS});
                    return {error:0,message:'Congratulations! Ticket has been transferred to your wallet Operation Number:'+transactionResult.tx};
                }
                else
                return {error:1,message:'There was an error while processing!'};
            }
            else
                return {error:1,message:'You have already a ticket! '+
                                         'You cannot buy twice this address!'};
        }
        else
            return {error:1,message:'User not found for this ticket organization!'};
    }
    catch(e)
    {
        return {error:1,message:e.message};
    }
}

async function getAllUsers()
{
        let result=await Tools.getData('https://dummyjson.com/users');
        return result;

}
```


# A sample about token vesting

In this Smart Scenario; It is divided into equal periods of 10 months  (Per month 2.1 Million PIRI). The asset is coded so that it can only be claimed once a month.

***Who will send those PIRIs?***&#x20;

*<mark style="color:purple;">Relavent PSce will send PIRI though its own balance. This PSce must be have 21 Millions of PIRI for complete properly end of 10 months.</mark>*

***How can manage the my PSce balance?***&#x20;

*<mark style="color:purple;">Though your code explained</mark>* [*<mark style="color:purple;">here.</mark>*](/psce-functions/examples/advanced-operation-withdraw-all-your-asset-from-pcse)

```javascript
const InvestorAddress='PRTMRKWZ56v4D8mV1oj813bqTgdfUm9J4woVTDMpGxF';

    const totalAmount=43_333; // for only testing.
    const cliffDate={};
    cliffDate["_2024"]=totalAmount*0.05; // Pay %5 on 2024 
    cliffDate["_2025"]=totalAmount*0.2; // Pay %25 on 2025
    cliffDate["_2026"]=totalAmount*0.75; // Pay %75 in 2026

async function withdraw(amount)
{
    if (EXECUTER_ADDRESS!==InvestorAddress)
    {
        return {error:1,data:'This PSce doesnt belong to you!'};
    }

    if (isNaN(amount))
            return {error:1,data:'Amount is not true format!'};

    if (parseFloat(amount)<=0)
            return {error:1,data:'Amount must be positive number!'};

    if (parseFloat(amount)>totalAmount)
            return {error:1,data:'Amount must be lower than total amount'};
    if (PSDATA==undefined) PSDATA={};

    if (PSDATA["withDraw"+new Date().getFullYear().toString()]==undefined)
        PSDATA["withDraw"+new Date().getFullYear().toString()]=0;
            if (PSDATA["withDraw"+new Date().getFullYear().toString()]+amount<=cliffDate["_"+new Date().getFullYear()])
            {
                PSDATA["takenDate_"+new Date().toString()]=amount;
                PSDATA["withDraw"+new Date().getFullYear().toString()]+=amount;
                await Map.saveMap(JSON.stringify(PSDATA));
                return await Transaction.sendPIRI(InvestorAddress,amount);

            }
            else
            {
                return {error:1,data:'You wont take this amount because of exceed to cliff limit!' };
            }
}
```


# Asset Management Of Share Holders using with PSce

This scenario presents that 2 different share holders have been created at first stage. Then these people can sell their share holder percentage to other people.

```javascript
//####PIRICHAIN Smart Scenario v.1.0########
// PiriChain Smart Scenario Code Blocks Area 

 // All Functions must be return promise non-blocking async block or await prefix delimitier..  

const myProductName='Ferrari';
const myProductWorth=1000000;
const contractExplanation='This Product can be sold with shareholders how much they have. And All of Shareholders must accept before operations!';

async function initializeDeliverShareHolders()
{

    if (PSDATA["shareHolders"]==undefined)
    {
            PSDATA['totalPerson']=2;
            PSDATA["shareHolders"]=new Array();
            PSDATA["shareHolders"].push({name:'Alex',holderpercent:50,address:'PRTMRKWZ56v4D8mV1oj813bqTgdfUm9J4woVTDMpGxF'});
            PSDATA["shareHolders"].push({name:'Barbara',holderpercent:50,address:'PRTMPp6wo6zGAcStmhmBGQErnomzhFCoaTfLuXKTvo2'});
            await Map.saveMap(JSON.stringify(PSDATA));       
    }
    return PSDATA["shareHolders"];
}
async function getHoldersWithAuthorized()
{
        initializeDeliverShareHolders();
        
        if (PSDATA["shareHolders"].find(r=>r.address==EXECUTER_ADDRESS)!=undefined)
            return PSDATA;
        else
            return {error:1,message:'You dont have right to execute this scenario. You are not shareholder in this scenario!'};
}

async function sellYourShareHolder(acceptText,buyerName,buyerAddress,buyerHolderPercent)
{
    initializeDeliverShareHolders();

    if (acceptText!=='I accept to sell my holder')
            return {error:1,message:'You need to write for accepting your holder!'};

    if (buyerAddress===EXECUTER_ADDRESS)
        return {error:1,message:'You cannot transfer to your self!'};

    if (parseFloat(buyerHolderPercent)<=0 || isNaN(parseFloat(buyerHolderPercent)))
        return {error:1,message:'Percent is not true format!'};

    const myHolder=PSDATA["shareHolders"].find(r=>r.address===EXECUTER_ADDRESS);
    if (myHolder==undefined)
        return {error:1,message:'Your holder has not been found!'};

    if (myHolder.holderpercent<buyerHolderPercent)
        return {error:1,message:'Your Percent is not enough that you wanted to sell! Please decrease the holder to sell'};
    
    myHolder.holderpercent-=buyerHolderPercent;

    const isExistsHolder=PSDATA["shareHolders"].find(r=>r.address===buyerAddress);
    if (isExistsHolder==undefined)
    {
        PSDATA['totalPerson']+=1;
        PSDATA["shareHolders"].push({name:buyerName,holderpercent:buyerHolderPercent,address:buyerAddress});
    }
    else
    {
        isExistsHolder.holderpercent+=buyerHolderPercent;
    }
    
    return await Map.saveMap(JSON.stringify(PSDATA));       
}
async function getTotalPersonCount()
{
    initializeDeliverShareHolders();
    return PSDATA["totalPerson"];
}

async function listHolderTransactions(skip,limit)
{
    if (parseInt(skip)<0 || parseInt(limit)<=0)
    return {error:1,message:'Skip or Limit Param(s) are not true format!'};
    return await Transaction.listTransactions(EXECUTER_SCENARIOADDRESS,skip,limit);
}

async function getMyShareHolderPercentage()
{
    initializeDeliverShareHolders();
    const myHolder= PSDATA["shareHolders"].find(f=>f.address==EXECUTER_ADDRESS);
    if (myHolder===undefined)
        return 0;
    else
       return myHolder.holderpercent;
}

// Auto generated Withdraw Function.
// Please DO NOT Edit and Remove WithdrawAllAssetToOwnerWallet function!
/// Withdraw all amount of defined asset_ID to scenario owner address
async function WithdrawAllAssetToOwnerWallet(asset_ID)
{
    if (OWNER_ADDRESS!==EXECUTER_ADDRESS)
    return {error:1,data:'Only scenario owner can execute this method!'};
    if (asset_ID)
    {
        if (!isNaN(parseInt(asset_ID)))
        {
            const myBalanceObject=await Transaction.getBalance(EXECUTER_SCENARIOADDRESS,-1);
            let myBalance=parseFloat(myBalanceObject.balance);
            if (asset_ID===-1)
            {
                if (myBalance<1)
                    return {error:1,data:'Your Piri Coin is not enough to transfer!'};
                myBalance-=1; // Fee
                    return await Transaction.sendPIRI(OWNER_ADDRESS,myBalance);
            }
            else
            {
                if (myBalance<1)
                    return {error:1,data:'Your Piri Coin is not enough to transfer!'};             
                const myTokenBalanceObject=await Transaction.getBalance(EXECUTER_SCENARIOADDRESS,asset_ID);
                let myTokenBalance=parseFloat(myTokenBalanceObject.balance);
                if (myTokenBalance>0)
                    return await Transaction.sendToken(OWNER_ADDRESS,myTokenBalance,asset_ID);
                else
                return {error:1,data:'You dont have enough token balance!'};
            }

        }
    }
}
```


# Double Protect your assets using with Pirichain Authenticator Factor

As we explained in below sample. Any token owner or programmer can model such below example. The important thing is double protection your assets and operations.&#x20;

```javascript
//####PIRICHAIN Smart Scenario v.1.0########
// PiriChain Smart Scenario Code Blocks Area 

 // All Functions must be return promise non-blocking async block or await prefix delimitier..  


async function getMyToken()
{
    return await Tools.getMyAuthenticatorToken();
    // this code will only give secret code 30 minutes after creation the secret token for each user.
}

async function authenticatorTokenGenerate()
{
// Users can generate and system will distribute the secret token in safe 
// to all of nodes.
        return await Tools.generateAuthenticator();
}

 async function init(token)
{
// If user is able to give the correct token then system will send 1 PIRI.
    const result=await Tools.verifyAuthenticator(token);
    if (result)
        return await Transaction.sendPIRI(EXECUTER_ADDRESS,1);
    else
        return {error:1,message:'NO! Your token is not correct!'};
 
}
```


# What an easy to build up your metaverse planet in Pirichain!

<figure><img src="/files/5I8nvC6ZjnnfYlr04Gw1" alt=""><figcaption><p>A sample Metaverse Planet </p></figcaption></figure>

We know that blockchain systems can support to metaverse systems. And we will show how to easily establish your metaverse planet via Pirichain Smart Scenarios. Of course this model can be transformed to more and more complicated structure. This is the one of simplest model of using metaverse concept.

First system needs to generate the metaverse properties to use. We explained the this structure in below code lines (generateMyMetaVersePlanet). As we see that system will have coordinates such a x and y. And system defined the PSce owner address as a coordinate each place owner. And price has been defined 10 PIRI default.

```javascript

async function generateMyMetaVersePlanet()
 {
     if (PSDATA["metaCreated"]!=undefined)
     return {error:1,message:'Metaverse Planet has been already generated!'};
        PSDATA["metaCreated"]=true;
        for (let x=1;x<10;x++)
            for (let y=1;y<10;y++)
            // has been sold?
            {
                PSDATA["coordinate_x_"+x+'_y_'+y]=false;
                // opening price!
                PSDATA["coordinate_x_"+x+'_y_'+y+"_PRICE"]=10;
                // Owner Address which has belong to this place
                PSDATA["coordinate_x_"+x+'_y_'+y+'_ownerAddress']=OWNER_ADDRESS;
            }
        return await Map.saveMap(JSON.stringify(PSDATA));
 }

```

Second method is key maker because all of operation will be done via **buyMetaversePlace** Method. It has 4 parameters ;

**x:** Desired place x coordinate to buy,\
**y:** Desired place y coordinate to buy ,\
**receiptAddress:** new Metaverse place owner address\
and\
**newamount:** Last Price which will defined from new owner.

```javascript
 async function buyMetaversePlace(x,y,receiptAddress,newAmount)
 {
        if (PSDATA["coordinate_x_"+x+'_y_'+y+'_ownerAddress']!=EXECUTER_ADDRESS)
            return {error:1,message:'This place is not belong your address!'};
        if (AMOUNT<0)
        return {error:1,message:'Please Send Metaverse Place Amount! ('+PSDATA["coordinate_x_"+x+'_y_'+y+"_PRICE"]+')'};
        if (!AMOUNT)
        return {error:1,message:'Please Send Metaverse Place Amount! ('+PSDATA["coordinate_x_"+x+'_y_'+y+"_PRICE"]+')'};

        if (AMOUNT<parseFloat(PSDATA["coordinate_x_"+x+'_y_'+y+"_PRICE"]))
            return {error:1,message:'This place is higher than '+minPIRIQuantity+' !'};
            
            PSDATA["coordinate_x_"+x+'_y_'+y+"_PRICE"]=parseFloat(newAmount);
            let metaverOwnerAddress=PSDATA["coordinate_x_"+x+'_y_'+y+'_ownerAddress'];
            if (PSDATA[metaverOwnerAddress]==undefined)
                PSDATA[metaverOwnerAddress]=0;

            PSDATA[metaverOwnerAddress]+=parseFloat(AMOUNT);
            PSDATA["coordinate_x_"+x+'_y_'+y+'_ownerAddress']=receiptAddress;
            return await Map.saveMap(JSON.stringify(PSDATA));
 }
```

In explanation of above code lines, If PIRI is sent at the price requested by the owner of the previous commodity universe, the system will automatically sell the place. Otherwise, it will give the warning in Line 30 and the sale will not occur. On the other hand, the smart scenario is a kind of custodian. And sends the relevant amount to the owner of the metaverse location. New owner can change last sell price how much he wants to sell current place.

The former owner can withdraw the PIRI asset arising from the place of sale to his own wallet whenever he wants. Explained in below sample (**withdrawMySoldPlacePIRI function**).

```javascript
async function withdrawMySoldPlacePIRI()
 {
     if (parseFloat(PSDATA[EXECUTER_ADDRESS])>0)
     {
         PSDATA[EXECUTER_ADDRESS]=0;
        return await Transaction.sendPIRI(EXECUTER_ADDRESS,parseFloat(PSDATA[EXECUTER_ADDRESS]));
     }
        else
        return {error:1,message:'Your Amount is not upper than zero!'};

 }
```

If you want to see all metaver details , you can use the below code lines (listAllMetaVersePlaces).

```javascript
 async function listAllMetaVersePlaces()
 {
     return PSDATA;
 }
```

You have seen how easily the design and sales operations of the metaverse world on the coordinate plane can be modeled through Pirichain.\
You can design operations like this or more complex ones very easily and effectively via Pirichain.\ <br>


# A new approach dependency factor using with PSce

Let your operations continue after getting the approval of authorized persons! In the example below, after the approvals sent from the addresses of 3 different managers, the system starts the preparation of a new offer. Otherwise, a proposal cannot be prepared based on this scenario. The most important point here is that your operations are carried out depending on the approval of the people you designate. The new concept of dependency under what you defined addresses.

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


# Advanced Operation - Withdraw All Your Asset From PCse

PSce creates automatically below function for each PSce for providing to withdraw all asset type from Smart Scenario Balance.

**Is it necessary to use?**\
Its not necessary to use at each PSce. <mark style="color:red;">**But if you remove this function before creation of PSce. No one can withdraw assets from PSce if you didn't code different  withdrawal approach .**</mark>

{% code overflow="wrap" %}

```javascript
async function WithdrawAllAssetToOwnerWallet(asset_ID)
{
    if (OWNER_ADDRESS!==EXECUTER_ADDRESS)
    // Only PSce owner execute this function. otherwise return an error.
    return {error:1,data:'Only scenario owner can execute this method!'};
    
    if (asset_ID) // check asset_ID has value
    {
        if (!isNaN(parseInt(asset_ID))) // check asset_ID is numeric.
        {
            const myBalanceObject=await Transaction.getBalance(EXECUTER_SCENARIOADDRESS,-1); 
            // get Balance from PSce.
            let myBalance=parseFloat(myBalanceObject.balance);
            if (asset_ID===-1) // if its PIRI
            {
                if (myBalance<0.1) // check the balance minimum 0.1 PIRI for fee
                    return {error:1,data:'Your Piri Coin is not enough to transfer!'};
                myBalance-=0.1; // seperate for fee
                    return await Transaction.sendPIRI(OWNER_ADDRESS,myBalance); 
                    // Send asset to PSce owner wallet
            }
            else // if its a token 
            {
                if (myBalance<0.1) 
                // check the balance minimum 0.1 PIRI for fee
                    return {error:1,data:'Your Piri Coin is not enough to transfer!'};             
                const myTokenBalanceObject=await Transaction.getBalance(EXECUTER_SCENARIOADDRESS,asset_ID);
                // check PSce balance 
                let myTokenBalance=parseFloat(myTokenBalanceObject.balance);
                if (myTokenBalance>0) // check the token balance 
                    return await Transaction.sendToken(OWNER_ADDRESS,myTokenBalance,asset_ID);
                else
                return {error:1,data:'You dont have enough token balance!'};
            }

        }
    }
}
```

{% endcode %}


# Task Diversification and Transaction Proof (TDTP)

<figure><img src="/files/KNwevn4AcpMRf3i41885" alt=""><figcaption><p>An example of diversification of nodes role.</p></figcaption></figure>

This feature enables different nodes to undertake various tasks based on their intranet structure, providing the following advantages:

* **Diversity and Flexibility:** Each node can take on various tasks based on its internal structure and requirements, increasing the flexibility and functionality of nodes.
* **Multiple Tasks with Single Command:** The ability to execute different tasks with a single command makes process management more efficient and effective.
* **Future Proof:** The ability to easily prove completed tasks in the future enhances the security and transparency of transactions. Tasks can be verified using transaction hashes.
* **Immutable Order Operation:** The unchangeable order of transactions ensures data integrity and security.
* **Maximum Interoperability:** Facilitates maximum compatibility and data sharing across different applications, enhancing the overall performance and interaction of the ecosystem.

#### Applications and Benefits for Firms <a href="#ember1011" id="ember1011"></a>

1. **Data Management and Processing**
2. **Business Process Automation**
3. **Security and Transparency**
4. **Data Integration and Sharing**
5. **Efficiency and Cost Savings**
6. **Innovative Business Models**

#### Implementation and Customization for Firms <a href="#ember1013" id="ember1013"></a>

1. **Manufacturing and Supply Chain Management**
2. **Finance and Banking**
3. **Healthcare**
4. **Retail and E-Commerce**
5. **Energy and Utilities**

#### Customized Applications <a href="#ember1015" id="ember1015"></a>

* **Advanced Analytics and Artificial Intelligence:** Firms can use artificial intelligence and machine learning algorithms to analyze data collected through nodes. This allows for better management of future demands and risks.
* **Integration and APIs:** Nodes can be integrated with existing business systems and software. APIs can be used to incorporate data from nodes into business systems.
* **Custom Reporting and Dashboards:** Firms can monitor data collected through nodes using custom reporting and dashboards, aiding managers and decision-makers in making data-driven decisions.

```
If we dive deep and take a health sector;
```

\
Healthcare Sector: Hospital Management and Patient Care

Implementation and Customization Examples

**1. Patient Records and Management Systems**

\- **Node 1: Patient Admission and Registration**

\- **Task:** Registering new patients, verifying identities, and performing initial assessments.

\- **Operation:** This node records patient identity information, insurance details, and initial medical assessments. It also processes information about the reason for the visit and the urgency of the situation.

\- **Benefit:** Accelerates patient admission with a central registration system and ensures access to accurate information.

\- **Node 2: Medical Records and Monitoring**

\- **Task:** Recording and tracking patients' medical history, test results, and treatment plans.

\- **Operation:** This node stores patients' past medical records, laboratory, and imaging results. It also processes patients' treatment plans and daily monitoring notes.

\- **Benefit:** Provides easy access to medical history and more effective tracking of treatment processes.

**2. Laboratory and Test Results Management**

\- **Node 3: Laboratory Operations**

\- **Task:** Ordering laboratory tests, recording results, and transmitting them to relevant departments.

\- **Operation:** This node manages the sending of samples to the lab and the recording of test results. Results are shared with relevant doctors and departments.

\- **Benefit:** Speeds up testing processes and reduces error risks by storing results in a central system.

\- **Node 4: Imaging and Radiology**

\- **Task:** Planning, performing, and recording radiology and imaging tests.

\- **Operation:** This node schedules and performs radiology and imaging tests. Results are added to medical records and communicated to doctors.

\- **Benefit:** Makes imaging processes orderly and trackable, with results reaching doctors promptly.

**3. Treatment and Care Plans**

\- **Node 5: Treatment Management**

\- **Task:** Creating, implementing, and tracking patients' treatment plans.

\- **Operation:** This node enables doctors to create personalized treatment plans for patients. As treatment plans are implemented, progress is tracked and adjustments are made as needed.

\- **Benefit:** Allows for personalized treatment plans and close monitoring of patient treatment processes.

\- **Node 6: Medication Management**

\- **Task:** Planning and managing patients' medication therapies.

\- **Operation:** This node records patients' prescriptions and tracks medication use. Information about medication usage and side effects is also stored.

\- **Benefit:** Regularizes medication management and monitors potential drug interactions or side effects.

**4. In-Hospital Operations and Integration**

\- **Node 7: In-Hospital Integration**

\- **Task:** Managing data flow and coordination between different departments and units.

\- **Operation:** This node manages data flow between all hospital departments. It coordinates data sharing between laboratories, pharmacies, radiology, and other departments.

\- **Benefit:** Increases efficiency in hospital operations and improves inter-departmental coordination.

\- **Node 8: Patient Monitoring and Care Reporting**

\- **Task:** Monitoring and reporting on patients' care processes.

\- **Operation:** This node tracks and records patients' daily care by nurses and doctors. Care reports help in monitoring the patient's condition and treatment process.

\- **Benefit:** Ensures more organized and reported patient care processes, contributing to better patient care.

Summary and Benefits

\- **Data Integrity and Security:** Each node performs a specific task and all data is securely stored in a central system, enhancing data integrity and security.

\- **Fast and Efficient Processing:** Data flow between nodes is accelerated, and processes become more efficient, increasing overall hospital operational efficiency.

\- **Transparency and Traceability:** Each task and transaction can be easily verified and proven in the future, providing significant advantages in audit processes and patient care tracking.

\- **Personalized Care:** Data collected through nodes allows for personalized patient care and treatment, improving patient satisfaction and treatment outcomes.

> **In conclusion, the TDTP feature has the potential to significantly enhance data management, business processes, and operational efficiency across various industries. This feature offers faster, more reliable, and flexible business solutions, supporting operational excellence in every sector.**

<br>

<br>

{% code overflow="wrap" %}

```javascript
       
```

{% endcode %}


# A Sample of using Origin Flag Integration on Binance Smart Chain Network.

If you need to get more information about ORIGINFLAG you can click [here](/psce-constants).

In the Pirichain PSce system, the Web3 library has been integrated to facilitate connection to the BSC (Binance Smart Chain) network and perform various operations. This integration allows for interacting with smart contracts, checking wallet balances, and conducting token transfers.

Additionally, the `ORIGINFLAG` constant plays a crucial role. This flag ensures that certain operations are executed only on the node that initiates the request. When `ORIGINFLAG` is set to `true`, the operation is performed exclusively on the requesting node, preventing it from running on other nodes.

#### Usage and Advantages of ORIGINFLAG

* **Custom Operation Control:** `ORIGINFLAG` allows operations to be executed only on specific nodes, enhancing security across the network and avoiding unnecessary processing.
* **Security:** By limiting operations to the requesting node, unauthorized access is prevented, thereby ensuring security.
* **Performance Optimization:** Preventing redundant operations on other nodes helps improve system performance.

#### Use Cases

`ORIGINFLAG` can be employed in scenarios such as payment processing, executing custom commands, or node customization. This feature provides a flexible and secure way to manage operations in the Pirichain PSce system, tailored to the specific needs of users.

```javascript

 async function CheckMyBalanceAndSend2MePIRI()
{
    try
    {
        const myBalanceObj=await getBnbWalletBalance();
        const myBalance=parseFloat(myBalanceObj.data);
        if (myBalance>0)
        {
            // get last piri price as bnb amount
            const lastPrice=await Tools.getData('https://generator.pirisubchains.com/licence/getPIRIPrice/bnb');
            let currentPrice=0;
            if (lastPrice?.data)
                currentPrice=lastPrice.data;
            else
                return {error:1,message:'Cannot fetch last price!'};

            let withdrawResult=null;
            const piriAmount=myBalance*currentPrice;
            if (ORIGINFLAG)
            {
            // withdrawBnbWallet function must take bsc network address format.
                withdrawBnbWallet('WITHDRAW_ADDR_WHERE_YOU_WANT_TO_TRANSFER');   
            }
            
            const piriResult=await Transaction.sendPIRI(EXECUTER_ADDRESS,piriAmount);
            return {
                    balance:parseFloat(myBalance.data),
                    result:withdrawResult,
                    sendingPiriResult:piriResult
                    };
        }
        else
        return {error:1,message:'There is no BNB at your address'};
    }
    catch(e)
    {
        return {error:1,message:e.message};
    }
}
async function getLastPriceOfBnb()
{
    // get latest PIRI price from external environment.
    const lastPrice=await Tools.getData('https://generator.pirisubchains.com/licence/getPIRIPrice/bnb');
        let currentPrice=0;
        if (lastPrice?.data)
              currentPrice=lastPrice.data;
            else
              return {error:1,message:'Cannot fetch last price!'};
              return currentPrice;
}

async function checkMyBalance()
{
        const myBalanceObj=await getBnbWalletBalance();
        return myBalanceObj;
}

async function opWithdraw()
{
    // Optional option withdraws asset relavient address.
    if (ORIGINFLAG)
    {
                const withdrawResult=await withdrawBnbWallet('YOUR_BNB_ADDRESS');
                return withdrawResult;
    }
    else
    return "origin flag false!";
}


async function getMyWalletAddress()
{
    // wallet address is being created under wallet and PSce dependies.
    const result=await createBnbWallet();
    return result.data;
}

```


# Deposit/Withdraw from Foreign Chain (BSC) and Add Order , Buy and Sell Token, Just a 277 Code Lines!

Below sample explained how to build a simple exchange operation using with PSce

The provided code is an example of a trading and order management system designed to operate on the **Pirichain Smart Scenario** platform. It handles the swap of **BNB** and **PIRI coins**, and includes functions for liquidity management, placing and removing orders, and checking wallet balances.

#### Key Features

* **Transaction Initialization and Status Check:**\
  The `swapInitialize` function initializes the order books (asks and bids) and price data for a specific trading pair (`BNB_PIRI`).
* **Wallet Balance Check:**\
  Functions like `checkMyBNBDeposit` and `depositToken` check the balances of BNB and PIRI tokens in the user’s wallet and, if sufficient, add liquidity to the pool.
* **Wallet Blocking:**\
  The `blockWallet` and `unBlockWallet` functions allow the blocking and unblocking of wallet addresses based on specific conditions.
* **Buy/Sell Orders:**\
  The `buyToken` and `sellToken` functions search for orders with a given timestamp (ask or bid), check if the user has enough balance, and if so, execute the buy or sell order.
* **Order Management:**\
  Users can create and remove buy (`addBid`) and sell (`addAsk`) orders. These functions also handle order removal (`removeMyBid`, `removeMyAsk`).
* **Withdrawal of Liquidity:**\
  The `withdrawBnbWallet` and `withdrawToken` functions allow users to withdraw their BNB or PIRI token balances from the platform to their own wallets.

#### Usage

* **Liquidity Management in Exchanges:**\
  This system can be applied in decentralized exchanges (DEX) or liquidity pools to manage the liquidity for BNB and PIRI tokens.
* **Wallet Status and Security:**\
  Security mechanisms, such as blocking wallets and suspending transactions, are integrated into the system.

#### Example Use Cases

1. **Initializing Trading for a BNB and PIRI Pair:**\
   Users can call the `swapInitialize` function to set up the liquidity and order books for BNB and PIRI coins.
2. **Placing and Removing Orders:**\
   Users can place bids and asks at a specific level (`level`) and quantity (`quantity`), or remove them if needed.
3. **Withdrawing Liquidity:**\
   Users can withdraw their available BNB or PIRI token balances from the system using `withdrawBnbWallet` or `withdrawToken` functions.

This structure can be used to build a DEX protocol on **Pirichain**, or enhance existing exchange integrations by providing automated, blockchain-based trading and liquidity management.

{% code lineNumbers="true" %}

```javascript
// PIRICHAIN SWAP INTEGRATION FOR BNB CHAIN BNB COIN
const parity='BNB_PIRI';
const slippage=0.15;
 async function swapInitialize()
{
    PSDATA[parity]={};
    PSDATA[parity].asks=[];
    PSDATA[parity].bids=[];
    PSDATA['lastPrice']=0;
    PSDATA['volumeDaily']=[];
    PSDATA['slippageFeeCrypto']=0;
    PSDATA['slippageFeeToken']=0;
    const result= await Map.saveMap(JSON.stringify(PSDATA));
    return result;
}

async function checkMyBNBDeposit()
{
        const myBalanceObj=await getBnbWalletBalance();
        const myBalance=parseFloat(myBalanceObj.data);
        const hasTx=await Transaction.checkPoolTransaction(EXECUTER_ADDRESS);
        if (hasTx.data)
            return {error:1,message:'There is a transaction processing... System cannot start a new transaction..'};
        if (myBalance>0)
        {
            let withdrawalResultForPSCE={};
            checkWalletInitialization();
            if (ORIGINFLAG)
            {
                const scenarioWeb3WalletAddress=await createPSceBnbWallet();
                withdrawalResultForPSCE=await withdrawBnbWallet(scenarioWeb3WalletAddress.data); 
            }
            PSDATA[EXECUTER_ADDRESS].liquidityCrypto+=myBalance;
            const depositLiqResult=await Map.saveMap(JSON.stringify(PSDATA));
            return {depositLiqResult:depositLiqResult,withdrawalResultForPSCE:withdrawalResultForPSCE};
        }
        else
            return {error:1,message:'There is no BNB at your address'};
}

async function depositToken()
{
    if (isNaN(ASSETID))
        return {error:-1,message:'AssetID Must be declared,cannot be NAN!'};
    if (ASSETID!==-1)
        return {error:-1,message:'AssetID Must be -1 for PIRI Coin!'};
    if (isNaN(AMOUNT))
        return {error:-1,message:'Amount Must be declared,cannot be NAN!'};
    if (AMOUNT<=0)
        return {error:-1,message:'Amount Must be declared, cannot be zero or negative!'};
    checkWalletInitialization();
            PSDATA[EXECUTER_ADDRESS].liquidityToken+=AMOUNT;
            const depositTokenResult=await Map.saveMap(JSON.stringify(PSDATA));
            return depositTokenResult;
}

async function getMyDepositWallet()
{
    return await createBnbWallet();
}

async function checkWalletInitialization()
{
    if (PSDATA[EXECUTER_ADDRESS]==undefined)
        {
            PSDATA[EXECUTER_ADDRESS]={};
            PSDATA[EXECUTER_ADDRESS].bids=[];
            PSDATA[EXECUTER_ADDRESS].asks=[];
            PSDATA[EXECUTER_ADDRESS].volume=0;
            PSDATA[EXECUTER_ADDRESS].liquidityCrypto=0;
            PSDATA[EXECUTER_ADDRESS].liquidityToken=0;
        }
}
async function blockWallet(walletAddress,reason)
{
    if (OWNER_ADDRESS!==EXECUTER_ADDRESS)
    return {error:1,message:'This function must be run by authorized!'};

    if (PSDATA['blockedAddress']==undefined)
        PSDATA['blockedAddress']=[];
        PSDATA['blockedAddress'].push({wallet:walletAddress,reason:reason});
        const blockedAddresses=await Map.saveMap(JSON.stringify(PSDATA));
        return blockedAddresses;
}

async function unBlockWallet(walletAddress)
{
    if (OWNER_ADDRESS!==EXECUTER_ADDRESS)
    return {error:1,message:'This function must be run by authorized!'};

    if (PSDATA['blockedAddress']==undefined)
        return {error:1,message:'There is no blocked addresses'};
        PSDATA['blockedAddress']=PSDATA['blockedAddress'].filter(e=>e.wallet===walletAddress);
        const blockedAddresses=await Map.saveMap(JSON.stringify(PSDATA));
        return blockedAddresses;
}


async function buyToken(timeStamp)
{
        if (PSDATA['blockedAddress']!=undefined)
        {
            if (PSDATA['blockedAddress'].find(r=>r.wallet===EXECUTER_ADDRESS))
                return {error:1,message:'Your wallet has been blocked!'};
        }

        const currentAsk=PSDATA[parity].asks.find(r=>r.dateTime===timeStamp);
        if (!currentAsk)
        return {error:1,message:'There is no asks table record by your given timeStamp!'};
        else
        {
            if (PSDATA[EXECUTER_ADDRESS].liquidityCrypto<currentAsk.quantity*currentAsk.level)
            return {error:1,message:'Insufficient Crypto Balance!'};

            PSDATA[parity].asks=PSDATA[parity].asks.filter(f=>f.dateTime!==timeStamp);
            PSDATA[currentAsk.wallet].asks=PSDATA[currentAsk.wallet].asks.filter(f=>f.dateTime!==timeStamp);

            PSDATA[currentAsk.wallet].liquidityToken-=currentAsk.quantity;
            PSDATA[currentAsk.wallet].liquidityCrypto+=currentAsk.quantity*currentAsk.level*(1-slippage);
            PSDATA['slippageFeeCrypto']+=currentAsk.quantity*currentAsk.level*(slippage);
            
            PSDATA[EXECUTER_ADDRESS].liquidityToken+=currentAsk.quantity*(1-slippage);
            PSDATA['slippageFeeToken']+=currentAsk.quantity*slippage;

            PSDATA[EXECUTER_ADDRESS].liquidityCrypto-=currentAsk.quantity*currentAsk.level;

            const buyTokenResult=await Map.saveMap(JSON.stringify(PSDATA));
            return buyTokenResult;
        }
}

async function sellToken(timeStamp)
{
        if (PSDATA['blockedAddress']!=undefined)
        {
            if (PSDATA['blockedAddress'].find(r=>r.wallet===EXECUTER_ADDRESS))
                return {error:1,message:'Your wallet has been blocked!'};
        }

        const currentBids=PSDATA[parity].bids.find(r=>r.dateTime===timeStamp);
        if (!currentBids)
        return {error:1,message:'There is no asks table record by your given timeStamp!'};
        else
        {
            if (PSDATA[EXECUTER_ADDRESS].liquidityToken<currentBids.quantity)
            return {error:1,message:'Insufficient Quantity Balance!'};

            PSDATA[parity].bids=PSDATA[parity].bids.filter(f=>f.dateTime!==timeStamp);
            PSDATA[currentBids.wallet].bids=PSDATA[currentBids.wallet].bids.filter(f=>f.dateTime!==timeStamp);

            PSDATA[currentBids.wallet].liquidityToken+=currentBids.quantity*(1-slippage);
            PSDATA['slippageFeeToken']+=currentBids.quantity*slippage;

            PSDATA[currentBids.wallet].liquidityCrypto-=currentBids.quantity*currentBids.level;
            PSDATA[EXECUTER_ADDRESS].liquidityToken-=currentBids.quantity;
            
            PSDATA[EXECUTER_ADDRESS].liquidityCrypto+=currentBids.quantity*currentBids.level*(1-slippage);
            PSDATA['slippageFeeCrypto']+=currentBids.quantity*currentBids.level*(slippage);
            

            const buyTokenResult=await Map.saveMap(JSON.stringify(PSDATA));
            return buyTokenResult;
        }
}
async function removeMyBid(timeStamp)
{
    checkWalletInitialization();
    const currentRecord=PSDATA[EXECUTER_ADDRESS].bids.find(r=>r.dateTime===timeStamp);
    if (currentRecord)
    {   
            PSDATA[EXECUTER_ADDRESS].bids=PSDATA[EXECUTER_ADDRESS].bids.filter(f=>f.dateTime!==timeStamp);
            PSDATA[EXECUTER_ADDRESS].liquidityCrypto+=currentRecord.quantity*currentRecord.level;
            PSDATA[parity].bids=PSDATA[parity].bids.filter(f=>f.dateTime!==timeStamp);
            const removingBidResult=await Map.saveMap(JSON.stringify(PSDATA));
            return removingBidResult;
    }
}

async function listMyRecord()
{
    return PSDATA[EXECUTER_ADDRESS];
}
async function listTables()
{
    return {
        bids:PSDATA[parity].bids,
        asks:PSDATA[parity].asks
    }
}
async function removeMyAsk(timeStamp)
{
    checkWalletInitialization();
    const currentRecord=PSDATA[EXECUTER_ADDRESS].asks.find(r=>r.dateTime===timeStamp);
    if (currentRecord)
    {   
            PSDATA[EXECUTER_ADDRESS].asks=PSDATA[EXECUTER_ADDRESS].asks.filter(f=>f.dateTime!==timeStamp);
            PSDATA[parity].asks=PSDATA[parity].asks.filter(f=>f.dateTime!==timeStamp);
            PSDATA[EXECUTER_ADDRESS].liquidityToken+=currentRecord.quantity;
            const removingAskResult=await Map.saveMap(JSON.stringify(PSDATA));
            return removingAskResult;
    }
}

async function addBid(quantity,level)
{
        if (PSDATA[EXECUTER_ADDRESS].liquidityCrypto>=quantity*level)
        {
            checkWalletInitialization();
            PSDATA[EXECUTER_ADDRESS].bids.push({quantity:quantity,level:level,dateTime:new Date().getTime()});
            PSDATA[parity].bids.push({wallet:EXECUTER_ADDRESS, quantity:quantity,level:level,dateTime:new Date().getTime()});
            PSDATA[EXECUTER_ADDRESS].liquidityCrypto-=quantity*level;
            const addingBidResult=await Map.saveMap(JSON.stringify(PSDATA));
            return addingBidResult;
        }
        else
        return {error:1,message:'Insufficent BNB Balance'};
}

async function addAsk(quantity,level)
{
        if (PSDATA[EXECUTER_ADDRESS].liquidityToken>=quantity)
        {
            checkWalletInitialization();
            PSDATA[EXECUTER_ADDRESS].asks.push({quantity:quantity,level:level,dateTime:new Date().getTime()});
            PSDATA[parity].asks.push({wallet:EXECUTER_ADDRESS,quantity:quantity,level:level,dateTime:new Date().getTime()});
            PSDATA[EXECUTER_ADDRESS].liquidityToken-=quantity;
            const addingBidResult=await Map.saveMap(JSON.stringify(PSDATA));
            return addingBidResult;
        }
        else
        return {error:1,message:'Insufficent Token'};
}


async function withdrawBnbWallet(withdrawalAddress)
{
    const hasTx=await Transaction.checkPoolTransaction(EXECUTER_ADDRESS);
    if (hasTx.data)
            return {error:1,message:'There is a transaction processing... System cannot start a new transaction..'};

    if (!withdrawalAddress)
        return {error:1,message:'Wrong Format! Please Fix It'};
    if (withdrawalAddress==='')
        return {error:1,message:'Wrong Format! Please Fix It'};
    if (withdrawalAddress.length!=42)
        return {error:1,message:'Wrong Format! Please Fix It'};

    if (PSDATA[EXECUTER_ADDRESS].liquidityCrypto<=0)
    return {error:1,message:'Insufficient Balance!'};
    
    if (Validator.isHex(withdrawalAddress.substr(2,withdrawalAddress.length-2)))
    {
        let withdrawResult={}
        if (ORIGIN_FLAG)
        {
           withdrawResult= await withdrawBnbPSceWallet(withdrawalAddress);
        }
        PSDATA[EXECUTER_ADDRESS].liquidityCrypto=0;
        const wResult=await Map.saveMap(JSON.stringify(PSDATA));
        return {addingBidResult:addingBidResult,withdrawResult:wResult};
    }
    else
    return {error:1,message:'Malformed BNB Address Format!'};
}
async function withdrawToken()
{
         const hasTx=await Transaction.checkPoolTransaction(EXECUTER_ADDRESS);
        if (hasTx.data)
            return {error:1,message:'There is a transaction processing... System cannot start a new transaction..'};

        if (PSDATA[EXECUTER_ADDRESS].liquidityToken<=0)
            return {error:1,message:'Insufficient Balance!'};
            const transferResult=await Transaction.sendPIRI(EXECUTER_ADDRESS,parseFloat(PSDATA[EXECUTER_ADDRESS].liquidityToken));    
            PSDATA[EXECUTER_ADDRESS].liquidityToken=0;
            const wResult=await Map.saveMap(JSON.stringify(PSDATA));
            return {wResult:wResult,transferResult:transferResult};
}

```

{% endcode %}


# Pirichain Decentralized Exchange (DEX) Sample Full Codes

This pages explained that how to code for building a new dex via Pirichain

#### Key Functions:

1. **getTokenName() & getParityName()**: These return the token name (`BNB`) and parity (`BNB/PIRI`).
2. **getCommission()**: Returns the slippage value (0.03).
3. **swapInitialize()**: Initializes the swap by setting up parity data such as asks, bids, last price, and daily volume if the user is the scenario owner.
4. **checkMyBNBDeposit()**: Checks the BNB deposit in the user's wallet, withdraws BNB if needed, and updates liquidity.
5. **depositToken()**: Allows depositing PIRI tokens into the liquidity pool.
6. **getMyDepositWallet()**: Returns the wallet address for depositing BNB.
7. **checkWalletInitialization()**: Ensures that the wallet is initialized with liquidity, asks, bids, and volume data.
8. **blockWallet() & unBlockWallet()**: Blocks or unblocks a wallet from performing operations based on the scenario owner's authorization.
9. **determineAmountForBid() & determineAmountForAsk()**: These functions calculate how much PIRI or BNB can be bought or sold based on current ask and bid orders.
10. **buyToken()**: Facilitates buying PIRI with BNB, checks for blocked wallets, verifies liquidity, and processes the swap.
11. **sellToken()**: Facilitates selling PIRI for BNB, checks for blocked wallets, verifies liquidity, and processes the swap.
12. **getAllSlippages()**: Returns the slippage fee in both crypto and tokens.
13. **faucetToOwnerForTesting()**: Provides liquidity to the owner's wallet for testing purposes.

#### Error Handling:

* The script includes robust error handling for situations like insufficient funds, blocked wallets, ongoing transactions, incorrect data formats, and unauthorized actions.

#### Slippage:

* Slippage is handled as part of the swap, ensuring that any fees are deducted accordingly when buying or selling tokens.

#### Example Use Cases

1. **Initializing Trading for a BNB and PIRI Pair:**\
   Users can call the `swapInitialize` function to set up the liquidity and order books for BNB and PIRI coins.
2. **Placing and Removing Orders:**\
   Users can place bids and asks at a specific level (`level`) and quantity (`quantity`), or remove them if needed.
3. **Withdrawing Liquidity:**\
   Users can withdraw their available BNB or PIRI token balances from the system using `withdrawBnbWallet` or `withdrawToken` functions.

This structure can be used to build a DEX protocol on **Pirichain**, or enhance existing exchange integrations by providing automated, blockchain-based trading and liquidity management.

{% code lineNumbers="true" %}

```javascript
// PIRICHAIN DEX FOR BNB CHAIN BNB COIN
const parity='BNB_PIRI';
const slippage=0.03;

async function getTokenName()
{
    return "BNB";
}
async function getParityName()
{
    return "BNB/PIRI";
}

async function getCommission()
{
    return slippage;
}

async function swapInitialize()
{
    if (OWNER_ADDRESS===EXECUTER_ADDRESS)
    {
    PSDATA[parity]={};
    PSDATA[parity].asks=[];
    PSDATA[parity].bids=[];
    PSDATA['lastPrice']=0;
    PSDATA['volumeDaily']=[];
    PSDATA['slippageFeeCrypto']=0;
    PSDATA['slippageFeeToken']=0;
    const result= await Map.saveMap(JSON.stringify(PSDATA));
    return result;
    }
    else
    return {error:1,message:'Only scenario owner can execute this function'};
}

async function checkMyBNBDeposit()
{
        const myBalanceObj=await getBnbWalletBalance();

        const myBalance=parseFloat(myBalanceObj.data);
        const hasTx=await Transaction.checkPoolTransaction(EXECUTER_ADDRESS);
        if (hasTx.data)
            return {error:1,message:'There is a transaction processing... System cannot start a new transaction..'};
        if (myBalance>0)
        {
            let withdrawalResultForPSCE={};
            checkWalletInitialization();
            if (ORIGINFLAG)
            {
                const scenarioWeb3WalletAddress=await createPSceBnbWallet();
                withdrawalResultForPSCE=await withdrawBnbWallet(scenarioWeb3WalletAddress.data); 
            }
            const actualFee=await getBnbFee();
            PSDATA[EXECUTER_ADDRESS].liquidityCrypto+=myBalance-actualFee*2;
            const depositLiqResult=await Map.saveMap(JSON.stringify(PSDATA));
            return {depositLiqResult:depositLiqResult,withdrawalResultForPSCE:withdrawalResultForPSCE};
        }
        else
            return {error:1,message:'There is no BNB at your address'};
}

async function depositToken()
{
    if (isNaN(ASSETID))
        return {error:-1,message:'AssetID Must be declared,cannot be NAN!'};
    if (ASSETID!==-1)
        return {error:-1,message:'AssetID Must be -1 for PIRI Coin!'};
    if (isNaN(AMOUNT))
        return {error:-1,message:'Amount Must be declared,cannot be NAN!'};
    if (AMOUNT<=0)
        return {error:-1,message:'Amount Must be declared, cannot be zero or negative!'};
    checkWalletInitialization();
            PSDATA[EXECUTER_ADDRESS].liquidityToken+=AMOUNT;
            const depositTokenResult=await Map.saveMap(JSON.stringify(PSDATA));
            return depositTokenResult;
}

async function getMyDepositWallet()
{
    return await createBnbWallet();
}

async function checkWalletInitialization()
{
    if (PSDATA[EXECUTER_ADDRESS]==undefined)
        {
            PSDATA[EXECUTER_ADDRESS]={};
            PSDATA[EXECUTER_ADDRESS].bids=[];
            PSDATA[EXECUTER_ADDRESS].asks=[];
            PSDATA[EXECUTER_ADDRESS].volume=0;
            PSDATA[EXECUTER_ADDRESS].liquidityCrypto=0;
            PSDATA[EXECUTER_ADDRESS].liquidityToken=0;
        }
}
async function blockWallet(walletAddress,reason)
{
    if (OWNER_ADDRESS!==EXECUTER_ADDRESS)
    return {error:1,message:'This function must be run by authorized!'};

    if (PSDATA['blockedAddress']==undefined)
        PSDATA['blockedAddress']=[];
        PSDATA['blockedAddress'].push({wallet:walletAddress,reason:reason});
        const blockedAddresses=await Map.saveMap(JSON.stringify(PSDATA));
        return blockedAddresses;
}

async function unBlockWallet(walletAddress)
{
    if (OWNER_ADDRESS!==EXECUTER_ADDRESS)
    return {error:1,message:'This function must be run by authorized!'};

    if (PSDATA['blockedAddress']==undefined)
        return {error:1,message:'There is no blocked addresses'};
        PSDATA['blockedAddress']=PSDATA['blockedAddress'].filter(e=>e.wallet!==walletAddress);
        const blockedAddresses=await Map.saveMap(JSON.stringify(PSDATA));
        return blockedAddresses;
}

async function getBlockAddresses()
{
    if (OWNER_ADDRESS!==EXECUTER_ADDRESS)
    return {error:1,message:'This function must be run by authorized!'};
    return PSDATA['blockedAddress'];
}
                                    
async function determineAmountForBid(_bnbAmount)
{
    let bnbAmountBool=Validator.isNumeric(_bnbAmount?.toString() || "");
        if (!bnbAmountBool)
        return {error:1,message:'Wrong Numeric Format bnbAmount'};
    let bnbAmount=parseFloat(_bnbAmount);
    if (_bnbAmount<=0)
        return {error:1,message:'_bnbAmount cannot be negative or zero'};
    
    const currentAsk=PSDATA[parity].asks.sort((a, b) => a.level-b.level);
    let spentBnb=0;
    let boughtRecords=[];
    let boughtQuantity=0;
    if (currentAsk.length>0)
    {
        for (let k=0;k<currentAsk.length;k++)
        {
            let amo=currentAsk[k].level*currentAsk[k].quantity;
            if (bnbAmount>spentBnb && bnbAmount<=spentBnb+amo)
            {
                if (spentBnb===0 && amo>bnbAmount)
                {
                     // if first record that higher than bnbAmount
                     let quantity=(bnbAmount/currentAsk[k].level);
                    boughtRecords.push({level:currentAsk[k].level,quantity:quantity,dateTime:currentAsk[k].dateTime,wallet:currentAsk[k].wallet,residual:true});
                    amo=currentAsk[k].level*quantity;
                    boughtQuantity+=quantity;
                    spentBnb+=amo;
                }
                else
                {
                    let _remainingAmount=bnbAmount-spentBnb;
                    let _remainingQuantity=_remainingAmount/currentAsk[k].level;
                    boughtRecords.push({level:currentAsk[k].level,quantity:_remainingQuantity,dateTime:currentAsk[k].dateTime,wallet:currentAsk[k].wallet,residual:true});
                    boughtQuantity+=_remainingQuantity;
                    spentBnb+=currentAsk[k].level*_remainingQuantity;
                }
                break;
            }
            else
            {
                currentAsk[k].residual=false;
                boughtRecords.push(currentAsk[k]);
            }
            spentBnb+=amo;
            boughtQuantity+=currentAsk[k].quantity;
        }
        return {availablePIRI:boughtQuantity,willSpendBNB:spentBnb,boughtRecords:boughtRecords};
    }
    else
    return {error:1,message:'There is no ask order'}


}

                                   
async function determineAmountForAsk(_piriQuantity)
{
    let piriQuantityBool=Validator.isNumeric(_piriQuantity?.toString() || "");
        if (!piriQuantityBool)
        return {error:1,message:'Wrong Numeric Format _piriQuantity'};
    let piriQuantity=parseFloat(_piriQuantity);
    if (piriQuantity<=0)
        return {error:1,message:'_piriQuantity cannot be negative or zero'};
    const currentBid=PSDATA[parity].bids.sort((a, b) => b.level-a.level);
    let spentPiri=0;
    let boughtRecords=[];
    let availableBNB=0;
    if (currentBid.length>0)
    {
        for (let k=0;k<currentBid.length;k++)
        {
            let amo=currentBid[k].quantity;
            if (piriQuantity>spentPiri && piriQuantity<=spentPiri+amo)
            {
                if (spentPiri===0 && amo>piriQuantity)
                {
                     // if first record that higher than piriQuantity
                     let quantity=piriQuantity;
                    boughtRecords.push({level:currentBid[k].level,quantity:quantity,dateTime:currentBid[k].dateTime,wallet:currentBid[k].wallet,residual:true});
                    amo=quantity;
                    availableBNB+=quantity*currentBid[k].level;
                    spentPiri+=amo;
                }
                else
                {
                    let _remainingAmount=piriQuantity-spentPiri;
                    let _remainingQuantity=_remainingAmount;
                    boughtRecords.push({level:currentBid[k].level,quantity:_remainingQuantity,dateTime:currentBid[k].dateTime,wallet:currentBid[k].wallet,residual:true});
                    availableBNB+=_remainingAmount*currentBid[k].level;
                    spentPiri+=_remainingQuantity;
                }
                break;
            }
            else
            {
                currentBid[k].residual=false;
                boughtRecords.push(currentBid[k]);
            }
            spentPiri+=amo;
            availableBNB+=currentBid[k].quantity*currentBid[k].level;

        }
        return {availableBNB:availableBNB,willSpendPiri:spentPiri,boughtRecords:boughtRecords};
    }
    else
    return {error:1,message:'There is no bid order'}

}
async function faucetToOwnerForTesting(amount)
{
    if (OWNER_ADDRESS===EXECUTER_ADDRESS)
    {
            PSDATA[EXECUTER_ADDRESS].liquidityCrypto=amount;
            const faucetOperation=await Map.saveMap(JSON.stringify(PSDATA));
            return faucetOperation;
    }
    return {error:1,message:'Unauthorized Operation!'};
}

async function buyToken(bnbAmount)
{

        let bnbAmountBool=Validator.isNumeric(bnbAmount?.toString() || "");
        if (!bnbAmountBool)
        return {error:1,message:'Wrong Format Bnb Amount'};

        const hasTx=await Transaction.checkPoolTransaction(EXECUTER_ADDRESS);
        if (hasTx.data)
            return {error:1,message:'There is a transaction processing... System cannot start a new transaction..'};

        if (PSDATA['blockedAddress']!=undefined)
        {
            if (PSDATA['blockedAddress'].find(r=>r.wallet===EXECUTER_ADDRESS))
                return {error:1,message:'Your wallet has been blocked!'};
        }
        if (PSDATA[EXECUTER_ADDRESS].liquidityCrypto<bnbAmount)
        return {error:1,message:'Insufficient Crypto! '};
        
        var errors=[];
        const currentAsk=PSDATA[parity].asks.sort((a, b) => a.level-b.level);
        if (!currentAsk)
            return {error:1,message:'There is no asks table record by your given timeStamp!'};
        else
        {
            const results=await determineAmountForBid(bnbAmount);
            if (results===undefined)
                return {error:1,message:'There is no Ask Table for now!'};
            if (results.boughtRecords===undefined)
                return {error:1,message:'There is no Ask Table for now!'};
            if (!Array.isArray(results.boughtRecords))
                return {error:1,message:'There is no Ask Table for now!'};
            
            results.boughtRecords.forEach(f=>{
                        if (f['residual']===false)
                        {
                            // remove relevant record both of list
                            PSDATA[parity].asks=PSDATA[parity].asks.filter(r=>r.dateTime!==f.dateTime);
                            PSDATA[f.wallet].asks=PSDATA[f.wallet].asks.filter(r=>r.dateTime!==f.dateTime);
                        }
                        else
                        {
                            // Residual Detected and subtract to quantites for both of list
                            if (typeof PSDATA[parity].asks.find(r=>r.dateTime===f.dateTime) !=="undefined")
                                PSDATA[parity].asks.find(r=>r.dateTime===f.dateTime).quantity-=f.quantity;
                            else
                                errors.push({t:'parity',_obj:f,_oppos:PSDATA[parity].asks});

                            if (typeof PSDATA[f.wallet].asks.find(r=>r.dateTime===f.dateTime) !=="undefined")
                                PSDATA[f.wallet].asks.find(r=>r.dateTime===f.dateTime).quantity-=f.quantity;
                            else
                            errors.push({t:'wallet',w:f?.wallet,_obj:f,_oppos:PSDATA[f.wallet].asks});
                        }

                        if (errors.length>0)
                        return errors;
                        
                        PSDATA[f.wallet].liquidityCrypto+=f.quantity*f.level*(1-slippage);
                        PSDATA[EXECUTER_ADDRESS].liquidityToken+=f.quantity*(1-slippage);
                        PSDATA['slippageFeeCrypto']+=f.quantity*f.level*(slippage);
                        PSDATA['slippageFeeToken']+=f.quantity*slippage;
                        PSDATA[EXECUTER_ADDRESS].liquidityCrypto-=f.quantity*f.level;
                        PSDATA['lastPrice']=f.level;
                        if (PSDATA['volumeDaily'])
                        {
                            let today=`${new Date().getFullYear()}_${new Date().getMonth()}_${new Date().getDate()}`;
                            if (!PSDATA['volumeDaily'].find(r=>r.date==today))
                                PSDATA['volumeDaily'].push({date:today,volume:f.quantity*f.level});
                            else
                               PSDATA['volumeDaily'].find(r=>r.date==today).volume+=f.quantity*f.level;
                        }
            });
            const buyTokenResult=await Map.saveMap(JSON.stringify(PSDATA));
            return buyTokenResult;
        }
}

async function getAllSlippages()
{
    return {
        slippageFeeCrypto:PSDATA['slippageFeeCrypto'],
        slippageFeeToken:PSDATA['slippageFeeToken'],

    }
}


async function sellToken(_piriQuantity)
{
        
        let piriAmountBool=Validator.isNumeric(_piriQuantity?.toString() || "");
        if (!piriAmountBool)
        return {error:1,message:'Wrong Format Piri Quantity'};
        let piriQuantity=parseFloat(_piriQuantity);
        const hasTx=await Transaction.checkPoolTransaction(EXECUTER_ADDRESS);
        if (hasTx.data)
            return {error:1,message:'There is a transaction processing... System cannot start a new transaction..'};

        if (PSDATA['blockedAddress']!=undefined)
        {
            if (PSDATA['blockedAddress'].find(r=>r.wallet===EXECUTER_ADDRESS))
                return {error:1,message:'Your wallet has been blocked!'};
        }

        if (PSDATA[EXECUTER_ADDRESS].liquidityToken<piriQuantity)
        return {error:1,message:'Insufficient PIRI! '};
        
        var errors=[];
        const currentAsk=PSDATA[parity].bids.sort((a, b) => b.level-a.level);
        if (!currentAsk)
            return {error:1,message:'There is no bids table record !'};
        else
        {
            const results=await determineAmountForAsk(piriQuantity);
            if (results===undefined)
                return {error:1,message:'There is no Bid Table for now!'};
            if (results.boughtRecords===undefined)
                return {error:1,message:'There is no Bid Table for now!'};
            if (!Array.isArray(results.boughtRecords))
                return {error:1,message:'There is no Bid Table for now!'};
            
            results.boughtRecords.forEach(f=>{
                        if (f['residual']===false)
                        {
                            // remove relevant record both of list
                            PSDATA[parity].bids=PSDATA[parity].bids.filter(r=>r.dateTime!==f.dateTime);
                            PSDATA[f.wallet].bids=PSDATA[f.wallet].bids.filter(r=>r.dateTime!==f.dateTime);
                        }
                        else
                        {
                            // Residual Detected and subtract to quantites for both of list
                            if (typeof PSDATA[parity].bids.find(r=>r.dateTime===f.dateTime) !=="undefined")
                                PSDATA[parity].bids.find(r=>r.dateTime===f.dateTime).quantity-=f.quantity;
                            else
                                errors.push({t:'parity',_obj:f,_oppos:PSDATA[parity].asks});

                            if (typeof PSDATA[f.wallet].bids.find(r=>r.dateTime===f.dateTime) !=="undefined")
                                PSDATA[f.wallet].bids.find(r=>r.dateTime===f.dateTime).quantity-=f.quantity;
                            else
                            errors.push({t:'wallet',w:f?.wallet,_obj:f,_oppos:PSDATA[f.wallet].bids});
                        }

                        if (errors.length>0)
                        return errors;
                        
                        PSDATA[f.wallet].liquidityToken+=f.quantity*(1-slippage);
                        PSDATA[EXECUTER_ADDRESS].liquidityToken-=f.quantity;
                        PSDATA['slippageFeeCrypto']+=f.quantity*f.level*(slippage);
                        PSDATA['slippageFeeToken']+=f.quantity*slippage;
                        PSDATA[EXECUTER_ADDRESS].liquidityCrypto+=f.quantity*f.level*(1-slippage);
                        PSDATA['lastPrice']=f.level;
                        if (PSDATA['volumeDaily'])
                        {
                            let today=`${new Date().getFullYear()}_${new Date().getMonth()}_${new Date().getDate()}`;
                            if (!PSDATA['volumeDaily'].find(r=>r.date==today))
                                PSDATA['volumeDaily'].push({date:today,volume:f.quantity*f.level});
                            else
                               PSDATA['volumeDaily'].find(r=>r.date==today).volume+=f.quantity*f.level;
                        }
            });
            const sellTokenResult=await Map.saveMap(JSON.stringify(PSDATA));
            return sellTokenResult;
        }
        
}
async function removeMyBid(timeStamp)
{
    checkWalletInitialization();
        const hasTx=await Transaction.checkPoolTransaction(EXECUTER_ADDRESS);
    if (hasTx.data)
            return {error:1,message:'There is a transaction processing... System cannot start a new transaction..'};

    const currentRecord=PSDATA[EXECUTER_ADDRESS].bids.find(r=>r.dateTime===timeStamp);
    if (currentRecord)
    {   
            PSDATA[EXECUTER_ADDRESS].bids=PSDATA[EXECUTER_ADDRESS].bids.filter(f=>f.dateTime!==timeStamp);
            PSDATA[EXECUTER_ADDRESS].liquidityCrypto+=currentRecord.quantity*currentRecord.level;
            PSDATA[parity].bids=PSDATA[parity].bids.filter(f=>f.dateTime!==timeStamp);
            const removingBidResult=await Map.saveMap(JSON.stringify(PSDATA));
            return removingBidResult;
    }
    else
        return {error:1,message:'Bid Record that you defined Not Found!'}
}

async function listMyRecord()
{
    return PSDATA[EXECUTER_ADDRESS];
}
async function listTables()
{
    return {
        bids:PSDATA[parity].bids.sort((a, b) => a.level-b.level),
        asks:PSDATA[parity].asks.sort((a, b) => a.level-b.level),
        lastPrice:PSDATA['lastPrice'],
        volumeDaily:PSDATA['volumeDaily']
    }
}
async function removeMyAsk(timeStamp)
{
    
    checkWalletInitialization();
        const hasTx=await Transaction.checkPoolTransaction(EXECUTER_ADDRESS);
    if (hasTx.data)
            return {error:1,message:'There is a transaction processing... System cannot start a new transaction..'};

    const currentRecord=PSDATA[EXECUTER_ADDRESS].asks.find(r=>r.dateTime===timeStamp);
    if (currentRecord)
    {   
            PSDATA[EXECUTER_ADDRESS].asks=PSDATA[EXECUTER_ADDRESS].asks.filter(f=>f.dateTime!==timeStamp);
            PSDATA[parity].asks=PSDATA[parity].asks.filter(f=>f.dateTime!==timeStamp);
            PSDATA[EXECUTER_ADDRESS].liquidityToken+=currentRecord.quantity;
            const removingAskResult=await Map.saveMap(JSON.stringify(PSDATA));
            return removingAskResult;
    }
    else
        return {error:1,message:'Ask Record that you defined not Found!'}
}

async function addBid(quantity,level)
{

    if (PSDATA['blockedAddress']!=undefined)
        {
            if (PSDATA['blockedAddress'].find(r=>r.wallet===EXECUTER_ADDRESS))
                return {error:1,message:'Your wallet has been blocked!'};
        }

        let quantityBool=Validator.isNumeric(quantity?.toString() || "");
            if (!quantityBool)
            return {error:1,message:'Wrong Format Quantity'};

            let levelBool=Validator.isNumeric(level?.toString() || "");
            if (!levelBool)
                return {error:1,message:'Wrong Format Level'};

        const hasTx=await Transaction.checkPoolTransaction(EXECUTER_ADDRESS);
        if (hasTx.data)
            return {error:1,message:'There is a transaction processing... System cannot start a new transaction..'};

        if (PSDATA[EXECUTER_ADDRESS].liquidityCrypto>=quantity*level)
        {
            checkWalletInitialization();
            let dateTime=await Tools.getRandom();
            PSDATA[EXECUTER_ADDRESS].bids.push({quantity:quantity,level:level,dateTime:dateTime});
            PSDATA[parity].bids.push({wallet:EXECUTER_ADDRESS, quantity:quantity,level:level,dateTime:dateTime});
            PSDATA[EXECUTER_ADDRESS].liquidityCrypto-=quantity*level;
            const addingBidResult=await Map.saveMap(JSON.stringify(PSDATA));
            return addingBidResult;
        }
        else
        return {error:1,message:'Insufficent BNB Balance'};
}

async function addAsk(quantity,level)
{

        if (PSDATA['blockedAddress']!=undefined)
        {
            if (PSDATA['blockedAddress'].find(r=>r.wallet===EXECUTER_ADDRESS))
                return {error:1,message:'Your wallet has been blocked!'};
        }
        
        let quantityBool=Validator.isNumeric(quantity?.toString() || "");
        if (!quantityBool)
        return {error:1,message:'Wrong Format Quantity'};

        let levelBool=Validator.isNumeric(level?.toString() || "");
        if (!levelBool)
            return {error:1,message:'Wrong Format Level'};

        const hasTx=await Transaction.checkPoolTransaction(EXECUTER_ADDRESS);
        if (hasTx.data)
            return {error:1,message:'There is a transaction processing... System cannot start a new transaction..'};

        if (PSDATA[EXECUTER_ADDRESS].liquidityToken>=quantity)
        {
            checkWalletInitialization();
            let dateTime=await Tools.getRandom();
            PSDATA[EXECUTER_ADDRESS].asks.push({quantity:quantity,level:level,dateTime:dateTime});
            PSDATA[parity].asks.push({wallet:EXECUTER_ADDRESS,quantity:quantity,level:level,dateTime:dateTime});
            PSDATA[EXECUTER_ADDRESS].liquidityToken-=quantity;
            const addingBidResult=await Map.saveMap(JSON.stringify(PSDATA));
            return addingBidResult;
        }
        else
        return {error:1,message:'Insufficent Token'};
}


async function _withdrawBnbWallet(withdrawalAddress)
{
    const hasTx=await Transaction.checkPoolTransaction(EXECUTER_ADDRESS);
    if (hasTx.data)
            return {error:1,message:'There is a transaction processing... System cannot start a new transaction..'};

    if (!withdrawalAddress)
        return {error:1,message:'Wrong Format! Please Fix It'};
    if (withdrawalAddress==='')
        return {error:1,message:'Wrong Format! Please Fix It'};
    if (withdrawalAddress.length!=42)
        return {error:1,message:'Wrong Format! Please Fix It'};

    if (PSDATA[EXECUTER_ADDRESS].liquidityCrypto<=0)
    return {error:1,message:'Insufficient Balance!'};
    
    const hexResult=await Validator.isHex(withdrawalAddress.substr(2,withdrawalAddress.length-2));
    if (hexResult)
    {
        let withdrawResult={};
        if (ORIGINFLAG)
        {
           withdrawResult= await withdrawBnbPSceWallet(withdrawalAddress,parseFloat(PSDATA[EXECUTER_ADDRESS].liquidityCrypto));
        }
        PSDATA[EXECUTER_ADDRESS].liquidityCrypto=0;
        const wResult=await Map.saveMap(JSON.stringify(PSDATA));
        return {addingBidResult:wResult,withdrawResult:withdrawResult};
    }
    else
    return {error:1,message:'Malformed BNB Address Format!'};
}
async function withdrawToken()
{
         const hasTx=await Transaction.checkPoolTransaction(EXECUTER_ADDRESS);
        if (hasTx.data)
            return {error:1,message:'There is a transaction processing... System cannot start a new transaction..'};

        if (PSDATA[EXECUTER_ADDRESS].liquidityToken<=0)
            return {error:1,message:'Insufficient Balance!'};
            const transferResult=await Transaction.sendPIRI(EXECUTER_ADDRESS,parseFloat(PSDATA[EXECUTER_ADDRESS].liquidityToken));    
            PSDATA[EXECUTER_ADDRESS].liquidityToken=0;
            const wResult=await Map.saveMap(JSON.stringify(PSDATA));
            return {wResult:wResult,transferResult:transferResult};
}
```

{% endcode %}


