Bako Connector
Quickstart
Installation
  1. Clone the repository

    In this walkthrough we are going to use a React template with TypeScript and Chakra UI.

     git clone https://github.com/infinitybase/bako-safe-dapp
  2. Install dependencies

    • fuels@0.76.12: the fuels SDK for TypeScript
    • bako-safe@0.0.51: the Bako Safe SDK for interacting with resources
    • @fuel-wallet/react@0.15.2: the fuels wallet for React
    • @fuel-wallet/sdk@0.15.2: the fuels wallet SDK
    • @fuels/react@0.15.3: the fuels SDK for React
    cd bako-safe-dapp &&
    yarn &&
  3. Understanding our project

    In the file src/App.tsx, we add the Fuel provider with the Bako Safe connector.

    import React from 'react'
    import ReactDOM from 'react-dom/client'
    import App from './App.tsx'
    import { FuelProvider } from '@fuel-wallet/react'
    import { BSafeConnector } from 'bsafe'
    import { ChakraProvider } from '@chakra-ui/react'
    import { defaultTheme } from './themes/default.ts'
     
    const bsafe = new BSafeConnector()
     
    ReactDOM.createRoot(document.getElementById('root')!).render(
      <React.StrictMode>
        <FuelProvider
          theme={'dark'}
          fuelConfig={{
            connectors: [bsafe],
            storage: null,
          }}
        >
          <ChakraProvider theme={defaultTheme}>
            <App />
          </ChakraProvider>
        </FuelProvider>
      </React.StrictMode>
    )

    By wrapping our application with the Fuel provider, we gain access to various hooks that facilitate interaction with the fuel wallet:

    const { fuel } = useFuel()
    const { account } = useAccount()
    const { disconnect } = useDisconnect()
    const { isConnected } = useIsConnected()
    const { isOpen, onOpen, onClose } = useDisclosure()

    In addition to the hooks from the example, several more can be explored via the link.

  4. Creating a Transaction

    When the user connects to the fuel wallet, they select a predicate previously created in the Bako Safe app. From there, the user can create transactions for that predicate and send them:

    async function handleTransfer() {
      if (!account) return
      const amount = bn.parseUnits(amountInput) ?? bn(1_000)
     
      const provider = await FuelWalletProvider.create(BSafe.get('PROVIDER'))
     
      const wallet = await fuel.getWallet(account, provider)
     
      const result = await wallet.transfer(Address.fromString(addressInput), amount, BaseAssetId, {
        gasPrice: BSafe.get('GAS_PRICE'),
        gasLimit: BSafe.get('GAS_LIMIT'),
      })
     
      const { id, status } = await result.waitForResult()
      console.log('result: ', { id, status })
    }

    Transactions are not immediately broadcast to the network; instead, they are sent to the Bako Safe servers and wait for the vault subscribers who generated the transaction to sign it. Once all signature requirements are met, the transaction is broadcast to the network.

  5. Calling a Contract

    The contract call operates similarly to a transaction. We use the vault again as a wallet and, having access to the contract's ABI generated earlier, call the contract's methods. Initially, create a simple contract to interact with Bako Safe:

    1. Create a folder named sway.

    2. Inside it, create a file src/main.sw:

      contract;
      use std::logging::log;
      abi MyContract {
          fn return_true(val1: u64) -> u64;
      }
      impl MyContract for Contract {
          fn return_true(val1: u64) -> u64 {
              log(val1);
              val1
          }
      }
    3. Add the file Forc.lock:

      ;[[package]]
      name = 'MyContract'
      source = 'member'
      dependencies = ['std'][[package]]
      name = 'core'
      source = 'path+from-root-BD9159206068AEC6'[[package]]
      name = 'std'
      source =
        'git+https://github.com/fuellabs/sway?tag=v0.46.1#512a3386f8961185188302f391ccc96553d23a7a'
      dependencies = ['core']
    4. Add the file Forc.toml:

      ;[project]
      authors = ['FuelLabs']
      entry = 'main.sw'
      license = 'Apache-2.0'
      name = 'MyContract'[dependencies]
    5. To set up the contract deployment on the network, add a file to the root of the project named fuels.config.ts:

      import { createConfig } from 'fuels'
       
      export default createConfig({
        providerUrl: 'https://beta-5.fuel.network/graphql',
        output: './src/contracts/',
        contracts: ['./sway'],
        privateKey: <YOUR_PK />,
      })
    6. At the root of the project, run the command yarn fuels build, and the folder src/contracts will be generated containing the build of our contract.

      yarn fuels build
    7. Deploy the contract to the network by executing the command yarn fuels deploy.

      yarn fuels deploy
    8. Now we have our contract on the network, and we can interact with it through our DApp:

      import { MyContractAbi__factory } from './contracts/contracts/factories/MyContractAbi__factory'
      import contractIds from './contracts/contract-ids.json'
       
      async function handleContractCall() {
        if (!account) return
        const provider = await FuelWalletProvider.create(BSafe.get('PROVIDER'))
        const wallet = await fuel.getWallet(account, provider)
        const contract = MyContractAbi__factory.connect(contractIds.myContract, wallet)
       
        const { value, transactionId } = await contract.functions
          .return_true(10)
          .txParams({
            gasPrice: bn(BSafe.get('GAS_PRICE')),
            gasLimit: bn(BSafe.get('GAS_LIMIT')),
          })
          .call()
      }
    9. Now you have your application connected. Vault subscribers in the Bako Safe app also receive a notification requesting their signature.

    If you have any questions, please feel free to contact us through our channels.

    Discord (opens in a new tab)

    Telegram (opens in a new tab)

    X (Twitter) (opens in a new tab)