In this tutorial we show you how to create Permits for authenticating a SNIP-20 contract. When you finish this Hello Permit tutorial you will have a web app connected to pulsar-2 with the ability to query the sSCRT balance using permits. Creating permits and connecting the app to Keplr.
Requirements
In order to go through this tutorial you'll need to have a Vue app created. You can find how to do it here. Also, install your dependencies and install Griptape.
# With npmnpm install && npm install @stakeordie/griptape.js# With yarnyarn && yarn add @stakeordie/griptape.js
We highly recommend have done Hello, Griptape before starting this tutorial for higher understanding of Griptape.
Getting started
This tutorial consist of these steps.
Grip an application.
Creating contract definition.
Import neccesary Griptape APIs and Contract Definition.
As you may know the first thing that we need to do is Grip our application, in this case our app is in src/main.js. This is how our main.js should look like.
import { createApp } from'vue';import App from'./App.vue';import { gripApp, getKeplrAccountProvider} from'@stakeordie/griptape.js';// Define node to connect to.constrestUrl='https://api.pulsar.griptapejs.com';// Get the Keplr provider.constprovider=getKeplrAccountProvider();// Define how the app is going to be mounted.functionrunApp() {createApp(App).mount('#app');}// Grip (AKA initialize) your application.gripApp(restUrl, provider, runApp);
Creating contract definition
Let's create a folder named contracts inside contracts, let's create a file called sscrt.js. You can copy and paste the next command.
mkdircontracts&&touch./contracts/sscrt.js
Importing APIs in src/contracts/sscrt.js
Now let's move and start working in src/contracts/sscrt.js, we need to import some APIs from Griptape.
createContractClient : Help us create an object based on a definition passed in as a parameter.
snip20Def : Is a pre-defined contract definition following Secret Network reference.
extendContract : API created to create a single contract definition binding two definition, similarly to inheritance in POO.
Defining custom contract definition
Defining a custom contract definition, in this case we have a definition with queries where we defined that we want to query the balance for sSCRT using permits.
constsscrt_permit= { queries: {// Getting permit from context getBalance({ permit }) {constquery= { balance: { } }//Every time we want to use permits we MUST send a query with this structurereturn { with_permit: { query, permit } } } }}
In a contract definition there are queries and messages. Both are objects with functions, all these functions are binding internally and always receive its first parameter what we called in Griptape as Context. In case you don't need any data from context to do the following. getBalance( _ , anyParameter,secondaryParameter).
Creating contract
Finally we just need to create our contract and export it.
enablePermit help us create a permit very easily and hasPermit returns a boolean indicating if a contract already has permit or not. All others APIs have already been explain in Hello tutorials before.
We also import our contract sscrt we just created in a section before.
Bootstrap app
Before boostrapping our app, we are going to define what our data object should look like and use one of our events APIs, onAccountAvailable explained in tutorials before (more info in Hello, Events).
With Griptape creating a permit is very easy, enablePermit is an API that receives two parameters, the first is a contract, in this case the one we imported before (sscrt), and a array of permissions to approve, in this case we want to see the balance.
Possible permissions for a SNIP-20 contract "balance" , "history", "allowance".
Possible permissions for a SNIP-721 contract "owner"
We are going to create a simple util function to create a permit. like the following.
exportdefault {// ...data//...mounted methods:{// ... more methodsasynccreatePermit() {this.loading =true;try {// Execute `enablePermit` message on sscrt contract.awaitenablePermit(sscrt,['balance']);this.isPermit =hasPermit(sscrt); } catch (e) {// ignore for now } finally {this.loading =false; } }, }}
Get Balance
To get the balance as easy as create a simple function like this.
exportdefault {// ...data//...mounted methods:{// ... more methodsasyncgetBalance() {try {this.loadingBalance =true;// Do nothing if we don't have a permit.if (!hasPermit(sscrt)) return;// In case we have a permit, fetch the balance.const { balance: { amount } } =awaitsscrt.getBalance();constbalance=coinConvert(amount,'6','human');this.balance = balance; } catch (error) {// ignore for now }finally{this.loadingBalance =false; } }, }}