Skip to content

Latest commit

 

History

History
 
 

dappkit

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

Celo DAppKit

DAppKit is a lightweight set of functions that allow mobile DApps to work with the Celo Wallet to sign transactions and access the user's account. This allows for a better user experience: DApps can focus on a great native experience without having to worry about key management. It also provides a simpler development experience, as no state or connection management is necessary.

DAppKit supports the following functionality:

  • Request permission to access account information and phone number from the Celo Wallet
  • Request permission to sign transaction(s) from the Celo Waller
  • Look up phone numbers using the Identity Protocol to find contacts using Celo.

DAppKit is currently built with the excellent Expo framework in mind. In the near future, we will make it more generic to all of React Native and possibly native stacks, but for now you get to take advantage of some awesome features like an incredibly easy setup, hot-reloading, and more.

Usage

This section walks you through the main functionalities of DAppKit. You can also find the result of this walkthrough on the expo base template on branch dappkit-usage.

DAppKit uses deeplinks to communicate between your DApp and the Celo Wallt. All "requests" that your DApp makes to the Wallet needs to contain the follwing meta payload:

  • requestId A string you can pass to DAppKit, that you can use to listen to the resopnse for that request
  • dappName A string that will be displayed to the user, indicating the DApp requesting access/signature.
  • callback The deeplink that the Celo Wallet will use to redirect the user back to the DApp with the appropriate payload. If you want the user to be directed to a particular page in your DApp. With Expo, it's as simple as Linking.makeUrl('/my/path')

Requesting Account Address

One of the first actions you will want to do as a DApp Developer is to get the address of your user's account, to display relevant informtion to them. It can be done as simply as:

(expo base template commit)

import { requestAccountAddress, waitForAccountAuth } from '@celo/dappkit'
import { Linking } from 'expo'

login = async () => {
  const requestId = 'login'
  const dappName = 'My DappName'
  const callback = Linking.makeUrl('/my/path')

  requestAccountAddress({
    requestId,
    dappName,
    callback,
  })

  const dappkitResponse = await waitForAccountAuth(requestId)

  this.setState({ address: dappkitResponse.address, phoneNumber: dappkitResponse.phoneNumber })
}

Once you have the account address, you can make calls against your own smart contract, or use ContractKit to fetch a user's balance:

(expo base template commit)

  const address = dappkitResponse.address
  this.setState({ address, phoneNumber: dappkitResponse.phoneNumber, isLoadingBalance: true })

  const kit = newKit('https://alfajores-forno.celo-testnet.org')
  kit.defaultAccount = address

  const stableToken = await kit.contracts.getStableToken()

  const [cUSDBalanceBig, cUSDDecimals] = await Promise.all([stableToken.balanceOf(address), stableToken.decimals()])
  const cUSDBalance = this.convertToContractDecimals(cUSDBalanceBig, cUSDDecimals)

  this.setState({ cUSDBalance, isLoadingBalance: false })

Get Contact List Addresses

For many real-world applications, your user will want to interact with their friends and family on your DApp. Celo has a built-in Identity Protocol that maps phone numbers to account addresses. You can use DAppkit to fetch that mapping for a user's contact list.

(expo base template commit)

import { fetchContacts } from "@celo/dappkit";
import * as Permissions from "expo-permissions";

const { status } = await Permissions.askAsync(Permissions.CONTACTS);

if (status != Permissions.PermissionStatus.GRANTED) {
  return
}

const { rawContacts, phoneNumbersByAddress } = await fetchContacts(kit.web3)

this.setState({ rawContacts, phoneNumbersByAddress })

Object.entries(this.state.phoneNumbersByAddress).map(([address, entry]) => {
  const contact = this.state.rawContacts[entry.id]
  return (
    <Button key={address} title={contact.name} onPress={() => {}} />
  )
})

Signing Transactions

Let's go from accessing account information to submitting transactions. To alter state on the blockchain, make a transaction object with your smart contract or any of the Celo Core Contracts in ContractKit. All that is left to do is to pass the transaction object to DAppKit.

(expo base template commit)

import {
  requestTxSig,
  waitForSignedTxs
} from "@celo/dappkit";

// Create the transaction object
const stableToken = await kit.contracts.getStableToken();
const decimals = await stableToken.decimals();
const txObject = stableToken.transfer(
  address,
  new BigNumber(10).pow(parseInt(decimals, 10)).toString()
).txo;

const requestId = "transfer";
const dappName = "My DappName";
const callback = Linking.makeUrl("/my/path");

// Request the TX signature from DAppKit
requestTxSig(
  kit.web3,
  [
    {
      tx: txObject,
      from: this.state.address,
      to: stableToken.contract.options.address,
      feeCurrency: FeeCurrency.cUSD
    }
  ],
  { requestId, dappName, callback }
);

const dappkitResponse = await waitForSignedTxs(requestId);
const tx = dappkitResponse.rawTxs[0];

// Send the signed transaction via web3
kit.web3.eth.sendSignedTransaction(tx).on("confirmation", async () => {
  const [cUSDBalanceBig, cUSDDecimals] = await Promise.all([
    stableToken.balanceOf(this.state.address),
    stableToken.decimals()
  ]);
  const cUSDBalance = this.convertToContractDecimals(
    cUSDBalanceBig,
    cUSDDecimals
  );

  this.setState({ cUSDBalance, isLoadingBalance: false });
})