Skip to content

Study Journal 08-08-2024

Published: at 10:51 AM

Where I’m at

What I learnt

Personal Crypto Project Architecture

A pratical example

Let’s consider a simple wallet connection button. I won’t go into the code here, but we’ll see it on a high level.

The wallet button does these things:

Let’s just rule out what we WON’T be using:

Using the chart, we’d then have to configure the following:

We’d also have to configure this, but not as much as the others (which are basically from scratch):

This is going to take a while, but it’s important to run through in detail so we get a clear understanding, or we re-evaluate our architecture model.

UI State

If you refer back to the outline of the simple wallet connect button, we can see that we’ll have to define the message that we want to display:

If we wanted say a traffic light indicator (e.g. green light for connected) for those connection statuses — then we’d have to create another $derived value, using the connection status value.

Also, we’d create a simple boolean state for isOpen to confirm if the dialog is open when the user clicked the button, and the connection status is connected.

So then the code looks like this:

const account = getAccount(config)

// Derived values
$derived message = (() => {
  switch (account.status) {
    case 'connecting':
      return "Wallet is attempting to connect ..."
    case 'reconnecting':
      return "Wallet is attempting to reconnect ..."
    case 'connected':
      return `Connected to: ${truncateAddress(account.address)}`
    case 'disconnected':
    default:
      return "No wallet is connected."
  }
})()

$derived indicator = (() => {
  switch (account.status) {
    case 'connected':
      return 'green'
    case 'connecting':
    case 'reconnecting':
      return 'yellow'
    case 'disconnected':
    default:
      return 'red'
  }
})()

// Simple state
let isOpen = $state(false)

// Helper function
function truncateAddress(address: string | undefined): string {
  if (!address) return ''
  return `${address.slice(0, 6)}...${address.slice(-4)}`
}

So now we have values that reacts to a change in Wagmi values, and returns a simple string message, gives us a traffic light indicator string, can tell if the confirmation dialog is open or not, and has a helper function to truncate the address string.

Application Logic

This is where we really start to get into the guts of the component itself. If you remember back to the wallet description it goes like this:

But let’s stay on track with our diagram. The application logic either affects the presentation layer of the Svelte Component, or it affects the Derived Web3 Data:

The code would then be looking like this:

async function handlePress() {
  switch (account.status) {
    case 'connecting':
    case 'reconnecting':
      return null;
    case 'connected':
      isOpen = true;
      break;
    case 'disconnected':
    default:
      await connect(config, { connector: injected() });
  }
}

Derived Web3 Data

Here is where we start to think of what data are flowing in from the Wallet Connection, this has more or less already been covered in the UI State, so we’ll just go over what’s relevant.

With this wallet button, there’s no need for blockchain data, so it’s exclusively what the Wallet Connection is feeding us.

What is derived from this is the Message and the Indicator, otherwise we don’t have any other data that we need to worry about.

Svelte Components

So we’re now into really defining what exactly the button needs to look like, which isn’t really the point of this exercise. It’s to show the decisions as we move slowly throughout the architecture so we don’t get lost.

But clearly in a real project, you’d then be creating the actual interface, including how it looks after the change has occurred. This case it’d be defining:

<button
  class="button"
  onclick={handlePress}
  >
  {message}
</button>

<dialog
  class="dialog"
  >
    <button
      class="dialog-yes"
      onclick={disconnect}
      >
      Yes
    </button>

    <button
      class="dialog-no"
      onclick={dismiss}
      >
      No
    </button>
</dialog>

Wallet Connection & Wagmi Logic

As you can see, the reason why we don’t really bother with going over this in much detail is because it’s already covered in the UI State / Derived Web3 data portions.

For this reason, we can see why we would not really need to bother with creating another system on top of this, as it’s already working into our application.

What I did

Consider supporting this blog