Skip to main content

JavaScript API

How to build the JavaScript interface for your smart contract.


Getting Started

Once your smart contract is built, tested, and deployed, you'll build a JavaScript API to interact with your smart contract. Navigate to the source folder to build and edit your JavaScript API.

1

Additional resources

Haven't written your unit tests? See Unit Tests before moving forward. The JavaScript API is written using React and makes use of both React Query and React Hooks. It also uses Ethers to interact with the Ethereum Network.

Source Folder

The source folder contains the following files for the JavaScript API.

  • moduleLibrary.ts - Library that contains the detailed functions that read & write to the blockchain.
  • useHook.ts - React hook that exposes your library to the react ecosystem.
  • Provider.tsx - Hyperverse modules use the React Context to expose state to child components.
  • environment.ts - Simple component that will identify which blockchain and network your module is being used under.
  • index.ts - Handles imports and exports for JavaScript API.

Update moduleLibrary.ts

The moduleLibrary.ts contains the detailed functions that read & write to the blockchain.

// Update file name to match smart module (ex. erc721Library.ts)
import { HyperverseConfig } from "@decentology/hyperverse";
import { EvmLibraryBase, getProvider } from "@decentology/hyperverse-evm";
import { ethers } from "ethers";
import { CancellablePromise } from "real-cancellable-promise";
import { getEnvironment } from "./environment";

export type ModuleLibraryType = Awaited<ReturnType<typeof ModuleLibraryInternal>>;
export function ModuleLibrary(...args: Parameters<typeof ModuleLibraryInternal>): CancellablePromise<ModuleLibraryType> {
return new CancellablePromise(ModuleLibraryInternal(...args), () => { });
}

async function ModuleLibraryInternal(
hyperverse: HyperverseConfig,
providerOrSigner?: ethers.providers.Provider | ethers.Signer
) {
const { FactoryABI, factoryAddress, ContractABI } = getEnvironment(
hyperverse.blockchain?.name!,
hyperverse.network
);
if (!providerOrSigner) {
providerOrSigner = getProvider(hyperverse.network);
}
const base = await EvmLibraryBase(
'CustomModule',
hyperverse,
factoryAddress!,
FactoryABI,
ContractABI,
providerOrSigner
);

// Add additional functionality to read and write from smart contract

return {
...base
// Return all additional consts as specified above
}
}
info

View an example of the completed erc721Library.ts file here

Update useHook.ts

useHook.ts provides hooks that expose your library to the React ecosystem.

// Update file name to match smart module (ex. useERC721.ts)
import { useState, useEffect } from 'react';
import { createContainer, useContainer } from '@decentology/unstated-next';
import { useEvm } from '@decentology/hyperverse-evm';
// Update imports to match smart module
import { ModuleLibrary, ModuleLibraryType } from './moduleLibrary';
import { useHyperverse } from '@decentology/hyperverse';

// Update name to match smart module
function ModuleState(initialState: { tenantId: string } = { tenantId: '' }) {
const { tenantId } = initialState;
const { address, connectedProvider, readOnlyProvider } = useEvm();
const hyperverse = useHyperverse();
// Update name to match smart module
const [hyperverseModule, setHyperverseModule] = useState<ModuleLibraryType>();


useEffect(() => {
// Update library to match smart module
const lib = ModuleLibrary(hyperverse, connectedProvider || readOnlyProvider).then(setHyperverseModule)
return lib.cancel;
}, [connectedProvider])


return {
// Update name to match smart module
...hyperverseModule,
tenantId,
};
}

// Update occurrences of module to match smart module
export const Module = createContainer(ModuleState);

export function useModule() {
return useContainer(Module);
}
info

View an example of the completed useERC721.ts file here

Update Provider.tsx

provider.tsx contains the React Context to expose state to child components.

import { FC } from "react";
import { QueryClientProvider, QueryClient } from "react-query";
// Update occurrences of module to match smart module
import { HyperverseModuleInstance } from "@decentology/hyperverse";
import { Module } from "./useHook";
const client = new QueryClient();

const Provider: FC<HyperverseModuleInstance> = ({ children, tenantId }) => {
if (tenantId == null) {
throw new Error("Tenant ID is required");
}
return (
// Update occurrences of module to match smart module
<QueryClientProvider client={client}>
<Module.Provider initialState={{ tenantId: tenantId }}>
{children}
</Module.Provider>
</QueryClientProvider>
);
};

export { Provider };
info

View an example of the completed ERC721 Provider.tsx here

Update environment.ts

environment.ts is a simple component that will identify which blockchain and network your module is being used under. This allows EVM modules to easily work with any supported EVM module

import {
Blockchain,
isEvm,
BlockchainEvm,
EvmEnvironment,
NetworkConfig,
} from '@decentology/hyperverse';

// Update occurrences of module in imports and exports to match smart module
import Factory from '../artifacts/contracts/ModuleFactory.sol/ModuleFactory.json';
import Contract from '../artifacts/contracts/Module.sol/Module.json';
import Contracts from '../contracts.json';
export const ContractABI = Contract.abi;
export const FactoryABI = Factory.abi;

const environment = Contracts as EvmEnvironment;

function getEnvironment(blockchainName: Blockchain, network: NetworkConfig) {
if (blockchainName == null) {
throw new Error('Blockchain is not set');
}
if (!isEvm(blockchainName)) {
throw new Error('Blockchain is not EVM compatible');
}

const chain = environment[blockchainName as BlockchainEvm];
if (!chain) {
throw new Error('Blockchain is not supported');
}
const env = chain[network.type];
return {
...env,
ContractABI,
FactoryABI,
};
}

export { environment, getEnvironment };
info

View an example of the completed ERC721 environment.ts file here

Update index.ts

index.ts handles imports and exports for JavaScript API.

// Update occurrences of module to match smart module
export { useModule } from "./useHook";
import { Provider } from "./Provider";
export { Provider } from "./Provider";
// Update occurrences of module to match smart module
export const ModuleName = "CustomModule";
export { ModuleLibrary } from "./moduleLibrary";
export const CustomModule = {
Provider,
ModuleName,
};
info

View an example of the completed ERC721 index.ts file here

Build UI Harness

You're now ready to start building your UI Harness!

โ†’
Step 5: UI Haress
ui-harness