# 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.