Code Monkey home page Code Monkey logo

txs's Introduction

aaaaaa

Concave txs

A plug and play, customizable way to manage user transaction status on your dapp

  • โœ… Out-of-the-box status notifications on top of @zag-js/toast (totally optional)
  • ๐ŸŽ‰ Easily customizable, or create your own with simple react hooks
  • ๐Ÿ”ฅ Using ethers and wagmi
  • โœจ Framework agnostic core at @pcnv/txs-core
  • ๐Ÿ“ฆ Tiny tiny, less than 3 kB gzipped

Install

pnpm add @pcnv/txs-react ethers wagmi @zag-js/react @zag-js/toast

# zag is not required if you want to create your own notification components
pnpm add @pcnv/txs-react ethers wagmi

Usage

Check the examples folder for a complete implementation

import {
  createTransactionsStore,
  ToastsViewport,
  TransactionsStoreProvider,
} from '@pcnv/txs-react'

// import a builtin toast component or create your own
import { ClassicToast } from '@pcnv/txs-react/toasts/ClassicToast'
import '@pcnv/txs-react/toasts/ClassicToast/styles.css'

const transactionsStore = createTransactionsStore()

...

// Add the provider to your app
// make sure its a children of WagmiConfig
<WagmiConfig client={...}>
  <TransactionsStoreProvider store={transactionsStore}>
    <ToastsViewport
      TransactionStatusComponent={ClassicToast}
      placement="top-end"
     />
    ...

And in your component

  import { usePrepareContractWrite, useContractWrite } from 'wagmi'
  import { useAddRecentTransaction } from '@pcnv/txs-react'

  ...

  const { config } = usePrepareContractWrite(...)
  const addTransaction = useAddRecentTransaction()
  const { write } = useContractWrite({
    ...config,
    onSuccess: (tx) => {
      // useContractWrite onSuccess means the transaciton was signed and sent
      addTransaction({
        hash: tx.hash,
        meta: {
          description: 'Your transaction description'
        },
      })
    },
  })

Hooks

useRecentTransactions

returns all transactions stored for the connected user in the connected chain

const recentTransactions = useRecentTransactions()

It also accepts a selector

// this component will only rerender when a new transaction is set as completed
const completedTransactions = useRecentTransactions((txs) =>
  txs.filter(({ status }) => status === 'completed'),
)

useAddRecentTransaction

Adds a transaction to be tracked, to the connected user/chain

const addTransaction = useAddRecentTransaction()
...
addTransaction({
  hash: '0x your transaciton hash',
  meta: {
    // metadata about the transaciton, description, type etc, more on the meta field below
  }
})

useRemoveRecentTransaction

Removes a connected user transaction by hash

const removeTransaction = useRemoveRecentTransaction()
...
removeTransaction(hash)

useClearRecentTransactions

Clears all transactions stored on the current connected user/chain

const clearTransactions = useClearRecentTransactions()
...
clearTransactions()

useTransactionsStoreEvent

Listens for an event from the store to execute a callback

useTransactionsStoreEvent(
  'added',
  useCallback((tx) => {
    // a new transaction was added, do something
  }, []),
)

Supported events are added, updated, removed, cleared, mounted

Useful if you are building your own notification solution

Maybe you want to display a confirmation dialog on transaction confimed. that could look something like this

useTransactionsStoreEvent(
  'updated',
  useCallback(
    (tx) => {
      if (tx.status === 'confirmed') displayTxConfirmedDialog(tx)
    },
    [displayTxConfirmedDialog],
  ),
)

Built in Components

Both detect prefers-color-scheme and style light/dark accordingly, you can force by passing a colorScheme prop, default is system

import { EmojiToast } from '@pcnv/txs-react/toasts/EmojiToast'
import '@pcnv/txs-react/toasts/EmojiToast/styles.css'

EmojiToast

import { ClassicToast } from '@pcnv/txs-react/toasts/ClassicToast'
import '@pcnv/txs-react/toasts/ClassicToast/styles.css'

ClassicToast

Some Defaults

The following can be configured thru props on ToastsViewport

  • showPendingOnReopen: should pop up the pending notification when the user closes and opens the app again while still pending? defaults to true
  • staleTime: if the user closed the app without a status update, for how long it's still relevant to display the update on reopen
  • stuckTime: transactions are considered stuck after 30min without a confirmation/rejection

Meta field

The meta field accepts anything serializable really, for example, instead of a single description you may want to have custom description for pending, completed and failed

Here's an example of how that could work

import {
  StoredTransaction,
  ToastsViewport,
  TransactionStatusToastProps,
  TypedUseAddRecentTransaction,
  TypedUseRecentTransactions,
  useRecentTransactions as _useRecentTransactions,
  useAddRecentTransaction as _useAddRecentTransaction,
} from '@pcnv/txs-react'

type TransactionMeta = {
  [status in StoredTransaction['status']]: string
}

const MyCustomNotification = (props: TransactionStatusToastProps<TransactionMeta>) => {
  const tx = props.transaction
  return <EmojiToast {...props} description={tx.meta[tx.status]} />
}

// you can rexport the hooks passing your new type as a generic to type check on use
// just remember to import from this file, and not @pcnv/txs-react
export const useRecentTransactions: TypedUseRecentTransactions<TransactionMeta> =
  _useRecentTransactions
export const useAddRecentTransaction: TypedUseAddRecentTransaction<TransactionMeta> =
  _useAddRecentTransaction

...
<ToastsViewport TransactionStatusComponent={MyCustomNotification} />

...

// and in you component ts will enforce this usage
const addTransaction = useAddRecentTransaction()
...
addTransaction({
  hash: tx.hash,
  meta: {
    pending: '...',
    completed: '...',
    failed: '...',
   },
})

Note Beware that everything included as meta will be saved to LocalStorage

Another example

This time only some properties are saved to localstorage based on the transaction type

type TransactionType = { type: 'approve'; amount: string; token: string } // | { ...more types }

type TransactionMetaToStatusLabel = {
  [Meta in TransactionType as Meta['type']]: (
    meta: Omit<Meta, 'type'>,
  ) => Record<StoredTransaction['status'], string>
}

const typeToStatusDescription = {
  approve: ({ amount, token }) => ({
    pending: `Approving ${amount} ${token}`,
    confirmed: `Successfully approved ${amount} ${token}`,
    failed: `Failed to approve ${amount} ${token}`,
  }),
} satisfies TransactionMetaToStatusLabel

const MyCustomNotification = (props: TransactionStatusToastProps<TransactionType>) => {
  const { meta, status } = props.transaction
  const description = typeToStatusDescription[meta.type](meta)[status]
  return <EmojiToast {...props} description={description} />
}

...

// and the hook usage
const addTransaction = useAddRecentTransaction<TransactionType>()
...
addTransaction({
  hash: tx.hash,
  meta: {
    type: 'approve', // typescript can auto suggest all available types and their required properties
    amount: 1,
    token: 'CNV'
   },
})

Enter & Exit Animations

Check Zagjs Docs

More

Check how's it being used it the concave repo

txs's People

Contributors

greg-schrammel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

greg-schrammel

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.