-
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
-
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 &&
-
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.
-
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.
-
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:
-
Create a folder named
sway
. -
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 } }
-
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']
-
Add the file
Forc.toml
:;[project] authors = ['FuelLabs'] entry = 'main.sw' license = 'Apache-2.0' name = 'MyContract'[dependencies]
-
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 />, })
-
At the root of the project, run the command
yarn fuels build
, and the foldersrc/contracts
will be generated containing the build of our contract.yarn fuels build
-
Deploy the contract to the network by executing the command
yarn fuels deploy
.yarn fuels deploy
-
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() }
-
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.
-