How to Integrate Scatter Desktop Wallet into your EOS Dapps using Reactjs
You might already be familiar with Scatter, a web/desktop wallet that makes it easy for ordinary users to store their private key and interact with apps. Integrating Scatter into apps can be tricky and, since Scatter is improving quickly, there have been some breaking changes introduced recently. I’ve had a bunch of people ask me about integrating Scatter, so I created this tutorial on how to integrate the latest version of Scatter Desktop into your distributed EOS application.
Create your Scatter Integration
We’re going to start by setting up Scatter inside of a Component and creating a transaction method. We’ll be able to use this anywhere in our application to enable users to sign transactions with Scatter.
Create Separate Scatter File and install dependencies
Make sure you import eosjs, scatterjs-core and scatterjs-plugin-eosjs2. Notice that we’re importing ‘scatterjs-plugin-eosjs2’ as our version of eosjs is greater than 16.
npm i -S eosjs
npm i -S scatterjs-core
npm i -S scatterjs-plugin-eosjs2
I’d highly recommend breaking out your core Scatter functionality into a separate file, which I typically call eosio-client.js.
import React from “react”;
import { Api, JsonRpc, JsSignatureProvider } from “eosjs”;
import ScatterJS from “scatterjs-core”;
import ScatterEOS from “scatterjs-plugin-eosjs2”;
Set up your network and endpoint
Next, we’ll want to define an endpoint and network. Your endpoint will be the location of your eosio contracts. If you are using a contract on your local machine, it will probably be something like http://localhost:8888. If you’ve deployed to Jungle Net, you can choose an endpoint from here: http://jungle.cryptolions.io/#apiendpoints. On the mainnet, most of the block producers have an api endpoint available and you can choose from any of these: https://www.eosdocs.io/resources/apiendpoints/.
We’re going to be accessing a contract deployed to the Jungle net, so we’ll use the following endpoint:
const endpoint = "http://jungle2.cryptolions.io:80";
We’ll set up our network next. Networks reference certain blockchains so you can get accounts and build signature providers. Note that we’re going to use the Jungle (test net) chainId in this example. If we were using the Mainnet, we would use a chainId of “aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906”. We also specify the blockchain being used since you can actually use Scatter with other blockchains like Ethereum and Tron.
const network = {
blockchain: "eos",
protocol: "http",
host: "jungle2.cryptolions.io",
port: 80,
chainId: "e70aaab8997e1dfce58fbfac80cbbb8fecec7b99cf982a9444273cbc64c41473"
};
Set up your Component
We’ll be able to instantiate an instance of the EOSIOClient from anywhere in our app, which will give us access to the variables and methods we’re creating here. We’re going to set up our constructor to accept one parameter, contractAccount. This will enable us to interact with multiple contracts within our application by passing in whichever contract name we want to use for a particular EOSIOClient instance.
export default class EOSIOClient extends React.Component {
constructor(contractAccount) {
super(contractAccount);
this.contractAccount = contractAccount;
Set up ScatterJS from within our constructor function. Make sure to pass in new ScatterEOS(), which will tell Scatter that we’re using “scatterjs-plugin-eosjs2”.
ScatterJS.plugins(new ScatterEOS());
Connect to Scatter and Create References
The last thing we’ll do within the constructor is connect to Scatter, create a reference to your account and create a reference to the fully initialized Scatter proxy. This is a lot of code, but it’s best to show it as a single block. Let me know in the comments if this needs more explanation.
try {
ScatterJS.scatter.connect(this.contractAccount).then(connected => {
if (!connected) return console.log("Issue Connecting"); const scatter = ScatterJS.scatter; const requiredFields = {
accounts: [network] // We defined this above
}; scatter.getIdentity(requiredFields).then(() => {
this.account = scatter.identity.accounts.find(
x => x.blockchain === "eos"
); const rpc = new JsonRpc(endpoint);
this.eos = scatter.eos(network, Api, { rpc });
}); window.ScatterJS = null; // Don't forget to do this!
}); } catch (error) {
console.log(error);
}
} // Close the constructor function
Note that it’s incredibly important that you set this.accounts above rather than hardcoding your account information or asking your users for the information.
Add a transaction method
You are now ready to sign transactions using Scatter. Whenever we call a transaction method on an EOSIOClient instance, we’re going to pass in an action name and data. This is a fairly simple transaction that we’ll use for basic interaction with our smart contracts. You can check out the eosjs documentation to structure more intricate (multiple action) methods, but this should work for most basic smart contract interaction.
transaction = (action, data) => {
return this.eos.transact(
{
actions: [
{
account: this.contractAccount,
name: action,
authorization: [
{
actor: this.account.name,
permission: this.account.authority
}
],
data: {
...data
}
}
]
},
{
blocksBehind: 3,
expireSeconds: 30
}
);
};
Congratulations, you have successfully set up your application so that users can sign transactions using Scatter. You can see a full version of this file here.
Create an EOSIOClient Instance in your Application
Make sure you import EOSIOClient into your file.
import EOSIOClient from "../utils/eosio-client";
Inside of your constructor, create a this.eosio reference. Make sure you head over too ScatterApps and add your app to the apps.json file. Pass that contract account name into your initializer.
this.eosio = new EOSIOClient(“YOUR APP NAME”);
Create your first transaction
We’re ready to create our first transaction. In this example, a user is going to buy RAM. In our interface, a user can enter a number of bytes to buy and click ‘Buy Now’, which triggers this function call.
handleBuyRam = async event => {
event.preventDefault();
let bytes = event.target.bytes.value; const actionName = "buyrambytes";
const actionData = {
buyer: accountName,
receiver: accountName,
bytes: parseInt(bytes)
}; try {
const result = await this.eosio.transaction(actionName, actionData); console.log(result);
this.getBalance(); // We can check a user's EOS balance.
} catch (e) {
console.log("\nCaught exception: " + e);
if (e instanceof RpcError) console.log(JSON.stringify(e.json, null, 2));
}
};
Next Steps
Here is another link to the full eosio-client.js file just in case you missed it above.
You can now set up Scatter, create multiple instances of EOSIOClient pointing at different contracts and call transactions. Please let me know if you’d like me to write a follow-up about getting information from the blockchain to display to your users!