# Getting Started

First, make sure you have installed the Pali Wallet extension (opens new window) in your browser.

Once the extension is installed you should be able to see the following method in your browser console: window.ConnectionsController. All functions detailed in the "Wallet" and "Tokens and Transactions" window should now be available.

WARNING

Make sure that once the wallet is connected that you are actually on the TestNetwork. Otherwise, you might be sending actual money!

# Building Extension locally

To build the API on a local server, first, get the code on our Github page (opens new window) or access it on the top right corner of this page.

Once you have cloned it to your desired directory, the files should be organized as follows:

├── demo
│   └── ...
└── extension
    ├── manifest.json
    ├── node_modules
    ├── package.json
    ├── package-lock.json
    ├── scratch
    ├── source
    ├── tsconfig.json
    ├── views
    ├── webpack.config.js
    └── yarn.lock


Enter the extension directory and run

yarn install 

This command might take a couple of minutes to complete. For the current version of this project, it is expected that your node module is on version 12.0 or higher. If it is not, here is a guide for updating NodeJS (opens new window).

When yarn install has completed, run

yarn run dev:chrome

This command should work if you are using chrome-based browsers (e.g. brave, chrome, chromium). Otherwise, examine the package.json file to see what other browsers are supported. For example, dev:firefox should work on firefox.

Wait for the extension to be fully running. Once it has stopped printing to the console, go to the extensions page on your browser (i.e. chrome://extensions). On the top right corner, you should see a button tagged developer mode; toggle it ON. There should now be, at the top left corner, a button load unpacked ; click it and set the path as your_path/pali_wallet/extension/extension/chrome . Now you should see the extension installed in your browser.

You can now open localhost in your browser. Next, we will learn how to build your first application and test the wallet functions.

# Building your first DApp

TIP

All of the considerations below follow up closely from a test App which is available on the Pollum labs repository (opens new window). Please feel free to download it and try functions directly.

To begin, we will create an EventListener to check if the extension is installed in the client browser. This is needed so we can be sure that the browser and the extension are interacting correctly.

The Pali Wallet extension is built on top of React. Therefore, the useState and useEffect hooks can be directly imported in this manner:

    import { useEffect, useState, useCallback } from "react";

Once you have React to work with, you can directly declare const variables. Some of these are especially relevant for this example:

  const [controller, setController] = useState(null);
  const [isInstalled, setIsInstalled] = useState(false);
  const [connectedAccount, setConnectedAccount] = useState(null);

Later you will learn how to access information stored in these variables through a test demo. For now they are only accessed through script.

The following is an example of how to initialize a simple application:

const App = () => {
  useEffect(() => {
    const callback = async (event) => {
      if (event.detail.SyscoinInstalled) {
        setIsInstalled(true);
        console.log('syscoin is installed');

        if (event.detail.ConnectionsController) {
          setController(window.ConnectionsController);
          console.log('controller is set');

          return;
        }

        return;
      }

      window.removeEventListener('SyscoinStatus', callback);
    }

    console.log('checking syscoin status');

    window.addEventListener('SyscoinStatus', callback);
  }, []);

  return (output);
}

There is a lot to unpack here; let's do that one step at a time. Here is an explanation of the output content:

The first part (before the last return) is calling the useEffect hook. That's where we declare the event to check if the extension is installed. That is the first thing that will run once the DApp is online.

What is happening in the background here:

The extension broadcasts a message to all open pages in the browser (your DApp included), then activates EventListeners that are waiting for said broadcast. When this happens, it feeds a SyscoinStatus object with the following values:

detail: { SyscoinInstalled: boolean, ConnectionsController: boolean}

If the extension is installed and has a controller available, both are true.

If successful, the isInstalled variable will be set to true and "connected" will print to the console. Furthermore, we define the controller variable as our actual ConnectionsController script for wallet functions. So now, if you wish to call the functions in ConnectionsController you can simply use the following:

 controller.function()

Otherwise, if the connection is not established (e.g. the Pali Wallet Extension is not installed, and SyscoinStatus returns false), the console simply prints "Not installed". If this is the case, then simply try to reinstall the extension.

Finally, this piece of code disconnects the EventListener since it is no longer necessary and replaces it with the callback hook to reference memoized info. Without that, your script would attempt to connect to the wallet every time the page changes.

The output could be any piece of information on your page. One could replace output in the code above to the following:

  return (
    <div className="app">
      <h2 className="app__title">Pali Wallet demo</h2>
      <div className="app__actions">
        <button
          className="app__button"
          disabled={!isInstalled}
          onClick={handleConnectWallet}
        >
          Connect/Change wallet
        </button>

        <button className="app__button" onClick={handleMakeSomething} disabled={!controller || !connectedAccount}>
          Make something
        </button>
      </div>
    </div>
  );

It should be clear for Javascript users that these are simply buttons that execute certain functions that modify variables when clicked. Let's clarify how these functions can look by demonstrating a case example.

# Testing functions on your DApp

Now that we have checked if the extension is installed, let's take the next step; provide a button to connect our wallet. We can define exactly what our buttons do. (For a list of wallet data functions you can check Wallet)

To connect the wallet one simply has to call

await controller.connectWallet();

This function should make the extension pop-up and ask for user info. You may realize, by checking the Wallet functions that connectWallet() is actually an async() and waits for a Promise, so a better way to call it, may be through

const handleConnectWallet = async (event) => {
  event.preventDefault();

  if (controller) {
    await controller.connectWallet();
  }
};

You should now be able to connect the wallet within your DApp. Also, with the way we have defined our buttons, once the wallet is connected, our test button should appear. When the button is used it will call whichever function you have defined inside its scope:

const handleMakeSomething = async () => {
  if (controller) {
    await controller.function();
  }
}

# Example 1: Retrieving an Object with wallet information.

Since connectWallet() function does not return any values per se (it only prints that the wallet connection is confirmed) we can also call the function getConnectedAccount() on our test button to get an object and modify the variables we have already declared. Since we now have a button for testing functions, the following snippet is an example on how to retrieve an Object (in this case, result), and further to pick some specific values from it.

const [connectedAccount, setConnectedAccount] = useState(null);

const handleMakeSomething = async () => {
  if (controller) {
    const account = await controller.getConnectedAccount();

    setConnectedAccount(account);

    console.log(`connected account address: ${account.address.main}}`)
  }    
};

your console output should look something like this

connected account address: tsys1q62y6wlqu0hsj5ey00keqz4yw6djk6mmmlxj8ar

# Example 2: Sending a Token

To send tokens directly from your script, you could write the above code as

const handleMakeSomething = async () => {
  const token = { 
    assetGuid: "2681611140",
    balance: 100000000,
    decimals: 2,
    symbol: "Coffees",
    type: "SPTAllocated"
  };
  
  if (controller) {
    await controller.handleSendToken({
      sender: "tsys1qvpjfee87n83d4kfhdwcw3fq76mteh92e4vdr8v", 
      receiver: "tsys1qqa5mgcsnum2rx3sa3ksq8rcwly9wtlj2d2ee74", 
      amount: 13,
      fee: 0.0001,
      token: token,
      isToken: true,
      rbf: true
    });
  }
};

This function call should pop-up the client's extension and ask them to confirm/approve the transaction.