Skip to content

Repository files navigation

AkashicLink

Mobile apps + Chrome extension

Wallet Container Diagram

graph LR
  linkStyle default fill:#ffffff

  subgraph diagram [Akashic System - AkashicLink - Components]
    style diagram fill:#ffffff,stroke:#ffffff

    subgraph 7 [AkashicLink]
      style 7 fill:#ffffff,stroke:#2e6295,color:#2e6295

      11("<div style='font-weight: bold'>Chrome Extension</div><div style='font-size: 70%; margin-top: 0px'>[Component]</div>")
      style 11 fill:#85bbf0,stroke:#5d82a8,color:#000000
      12("<div style='font-weight: bold'>Android</div><div style='font-size: 70%; margin-top: 0px'>[Component]</div>")
      style 12 fill:#85bbf0,stroke:#5d82a8,color:#000000
      13("<div style='font-weight: bold'>iOS</div><div style='font-size: 70%; margin-top: 0px'>[Component]</div>")
      style 13 fill:#85bbf0,stroke:#5d82a8,color:#000000
      14("<div style='font-weight: bold'>Web Preview (dev-only)</div><div style='font-size: 70%; margin-top: 0px'>[Component]</div>")
      style 14 fill:#85bbf0,stroke:#5d82a8,color:#000000
    end

  end
Loading

Warnings

  • Chrome extension does not support page reloads - whenever added a reload, perform a platform check as so:
import { isPlatform } from '@ionic/react';
...
isPlatform('mobile') && location.reload();

Installation

  1. Install all packages and setup .env file
cp .env.example .env # optionally edit .env to suit your needs
cp .env.example .env.preprod.local # If you need to build Android App. Copy as .env.production.local for production env
yarn install

Running locally as Web

  1. Start backend in app/backend
  2. Run
yarn start:dev
  1. You can use the following at root of the monorepo to start all at once
yarn start:all

Running locally as Chrome extension

  1. Build the extension by first building the full app (it moves the manifest.json file to the correct location), and then run the dev build
yarn build
yarn build:dev
  1. Go to browser://extensions/ and activate Developer Mode.

  2. Click Load unpacked and select the build folder. Extension should appear in browser.

  3. Source file updates will take around 5-6 seconds to recompile. See here for information of when the extensions needs reloading.

Building Chrome extension for production

  1. Set the .env with
REACT_APP_PUBLIC_URL=https://api.akashicscan.com
REACT_APP_API_BASE_URL=https://api.akashicscan.com/api
  1. Build extension
yarn build
  1. Zip the build folder

Running locally as Android App

  1. Install Android Studio, SDK v33 and virtual devices as instructed in Ionic Doc
  2. Build the App with
yarn sync:android
  1. Open the App automatically with
yarn serve:android
  1. In Android Studio, click "Run" to run the app in virtual device

Live reloading Android or ios App

add IS_LIVE_RELOAD=true in .env.preprod.local

yarn debug:ios

or

yarn debug:android

Styling

Styling is done with scss and 80% of what you would need to use can be found in this tutorial.

Any global styles, should be defined in the theme folder and imported in common.scss as so

@use "typography";
@use "layout";
@use "ion-popover";

For styling individual components, create a file-of-same-name.scss next to your .tsx file and target specific components adding className in the html:

<IonLabel className="my-class-1"></IonLabel>

or

<IonSelect interfaceOptions={{ htmlAttributes: { className: 'my-class-2'}}}>

Then use selectors, specificity and inheritance in the .scss file to target these components and their direct and indirect children:

  • .class1 .class2 (for when class2 is a descendant of a class1 element)
  • .class1.class2 (when an element is both class1 and class2)
  • +, > and other combinators to target direct children, sibling and adjacent components (see here)

Example below will apply the styles to any <IonSelect> and <IonList> that are descendants of a component with class my-custom-class-2 but not across the whole application.

.my-class-2 {
  /**
   * Add a frame to the selection menu and round the corners
   */
  ion-select-popover {
    border: 1px solid var(--ion-select-border) !important;
    border-radius: 4px;
  }

  /*
   * Ensures that selection menu is small enough to fit
   * under the selection button
   */
  ion-list {
    padding-top: 0px;
    padding-bottom: 0px;
    border-radius: 3px;
    max-height: 120px;
    overflow: scroll;
  }
}

Images

All UI images used by the wallet-extension are stored in public/assets. Only include files that are actually referenced by the app to keep the extension package small.

Craco

We are using create-react-app to manage all of the transpiling needed for the different .css, .html, .tsx files (under the hood it uses webpack). While it generally does a good job, we sometimes need to fine tune by overriding the config with craco to:

  • Process files outside the root directory. Specifically, instruct how to transpile .ts files in the sister packages inside the monorepo
  • Turn off optimisation when developing locally
  • Fix conflicts in the react version

Storybook

Open for instructions
  1. Create your stories in the ./storybook/stories/ folder using the following template:
import type { Meta, StoryObj } from "@storybook/react";

import { YOURCOMPONENT } from "../../src/YOUR-FOLDER";

const meta: Meta<typeof BackButton> = {
  title: "SUBTREENAME",
  component: YOURCOMPONENT,
};
export default meta;
type Story = StoryObj<typeof YOURCOMPONENT>;

export const Story1: Story = {};
export const Story2: Story = {};
export const Story3: Story = {};
  1. To customise the mock requests for each story, add a mock service worker (to either the meta or the individual stories)
export const Story1: Story = {
  parameters: {
    msw: {
      handlers: {
        GROUPNAME: [MOCK_REST_IMPLEMENTATIONg],
      },
    },
  },
};
  1. To customise the context that a component receives, specify the context e.g.
import { LocalAccountContext } from '../../src/components/PreferenceProvider';

export const Story1: Story = {
  decorators: [
    withReactContext({
      Context: IMPORT_CONTEXT_FROM ../../src/components/PreferenceProvide,r
      initialState: {
        localAccounts: [{
          identity: "mock-identity",
          username: "mock-username"
        }]
      },
    })
  ],
};
  1. To customise the path that the component is placed on, use the withMockPath decorator. Normally you would apply this to the meta object
import { akashicPayPath } from "../../src/routing/navigation-tabs";
import { urls } from "../../src/constants/urls";
import { withMockPath } from "../utils/mock-path";

const meta: Meta<typeof DashboardComponent> = {
  title: "Pages",
  component: DashboardComponent,
  decorators: [withMockPath(akashicPayPath(urls.loggedFunction))],
};

Provider Architecture

Detailed provider-focused doc: docs/PROVIDER_ARCHITECTURE.md

Note: This architecture description covers the browser extension provider integration path (background/content/injected + website usage). It does not attempt to describe any off-chain services or backend infrastructure.

Flow overview:

Website React (wallet-context) --> provider.request()
  Injected Script (injected.ts) --window.postMessage--> Content Script (content.ts)
    --> chrome.runtime.sendMessage --> Background (background.ts)
    <-- chrome.runtime.sendMessage <--
  Injected Script resolves promise & emits events -> React context updates

Key points:

  • Multiple environments (dev, staging, prod) can coexist. Each build registers its provider under window.__AKASHIC_PROVIDERS[env].
  • No global window.akashicLink fallback: the website explicitly selects env via NEXT_PUBLIC_ENV.
  • Background manages sessions, permissions per origin, and approval popups.
  • Content script enforces allowed-origin gating and injects the provider script only on permitted domains.
  • Events (accountsChanged, disconnect, popupOpened, popupClosed) propagate background -> content -> injected -> dApp listeners.

See the full architecture doc for diagrams, sequence details, and extension RPC method list.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages