Skip to main content

Aspect Structure

Aspect, executed on the Aspect-Runtime, follow a specific development pattern that utilizes WebAssembly (Wasm) syntax for coding, subsequently compiling it into WebAssembly modules.
This guide offers an overview of Aspect structure using a simple example, providing insights into the fundamental components of Aspects.

A simple Aspect

Paving the way to your first Aspect module.

1. Init a New Project

Make sure that a recent version of Node.js and its package manager npm are installed, then switch to a new directory and initialize a new Node.js module as usual:

npm install -g @artela/aspect-tool

mkdir -p apsect-demo && cd apsect-demo

aspect-tool init

npm install

The init command automatically creates the recommended directory structure and configuration files.

.
├── README.md
├── asconfig.json
├── aspect <-- Your aspect code resides here
│   └── index.ts <-- Entry functions for the aspect
├── contracts <-- Place your smart contracts here
├── package.json
├── project.config.json
├── scripts <-- Utility scripts, including deploying, binding and etc.
│   ├── aspect-deploy.cjs
│   ├── bind.cjs
│   ├── contract-call.cjs
│   ├── contract-deploy.cjs
│   ├── contract-send.cjs
│   └── create-account.cjs
├── tests
└── tsconfig.json

2. Create a Aspect

Within the ./aspect directory of your project, create your aspect files with a .ts extension. For example, create a HelloWorld.ts file:

import {
allocate,
entryPoint,
execute,
IPostContractCallJP,
IPostTxExecuteJP,
PostContractCallInput,
PostTxExecuteInput,
sys,
uint8ArrayToHex,
} from "@artela/aspect-libs";

/**
* Please describe what functionality this aspect needs to implement.
*
* About the concept of Aspect @see [join-point](https://docs.artela.network/develop/core-concepts/join-point)
* How to develop an Aspect @see [Aspect Structure](https://docs.artela.network/develop/reference/aspect-lib/aspect-structure)
*/
class HelloWorldAspect implements IPostContractCallJP, IPostTxExecuteJP {
postTxExecute(input: PostTxExecuteInput): void {
throw new Error("Method not implemented.");
}
/**
* isOwner is the governance account implemented by the Aspect, when any of the governance operation
* (including upgrade, config, destroy) is made, isOwner method will be invoked to check
* against the initiator's account to make sure it has the permission.
*
* @param sender address of the transaction
* @return true if check success, false if check fail
*/
isOwner(sender: Uint8Array): bool {
return true;
}

/**
* postContractCall is a join-point which will be invoked after a contract call has finished.
*
* @param input input to the current join point
*/
postContractCall(input: PostContractCallInput): void {
let txData = uint8ArrayToHex(input.call!.data);

// if call `world` function then revert, 30b67baa is method signature of `world`
if (txData.startsWith("30b67baa")) {
sys.revert("the function `world` not available");
}
}
}

// 2.register aspect Instance
const aspect = new HelloWorldAspect();
entryPoint.setAspect(aspect);

// 3.must export it
export {execute, allocate};

Only a Class that has implemented join points can be referred to as an Aspect. An Aspect implementing the Operation interface can be invoked by the Entity of Aspect (EoA).

Join points

Operation interface

After implementing the Aspect class, it is necessary to register the Aspect instance to entryPoint.


const aspect = new HelloWorldAspect();
// register join point
entryPoint.setAspect(aspect);

// register Operation, if the class implements the Operation interface
entryPoint.setOperationAspect(aspect);

3. Export EntryPoint

When the message is sent to the Aspect-Runtime, a function called "entryPoint" is called. Aspect have a couple corresponding to different message types: execute, allocate.

export {execute, allocate};

4. Compile

The assembly directory, which contains the AssemblyScript sources compiled into WebAssembly, can now be transformed into WebAssembly by executing the build command found in assembly/index.ts.

npm run aspect:build

Doing so will emit the compiled binaries, bindings and definition files to the build/ directory.

├── build
│   ├── debug.d.ts // debug TypeScript declaration file
│   ├── debug.js // debug JavaScript declaration file
│   ├── debug.wasm //debug WebAssembly bytecode file
│   ├── debug.wasm.map //debug WebAssembly output source map file
│   ├── debug.wat // debug WebAssembly text output file
│   ├── release.d.ts // release TypeScript declaration file
│   ├── release.js // release JavaScript declaration file
│   ├── release.wasm //release WebAssembly bytecode file
│   ├── release.wasm.map //release WebAssembly output source map file
│   └── release.wat // release WebAssembly text output file

Summary

  • Currently only provides the Aspect development package based on the AssemblyScript language
  • To implement an Aspect, it is required to define and implement "join points." Additionally, by implementing the "Operation interface," the Aspect becomes invokable by the Entity of Aspect (EoA).
  • After developing the Aspect, it is necessary to register the join points with the Entrypoint and then export the Entrypoint.
  • Compile to check the Aspect for errors, and get the WebAssembly bytecode file.
  • Since the AssemblyScript project does not provide features such as Aspect deployment, binding, calls, etc., you need to use additional tools such as web3.js to communicate with Artela Blockchain. We recommend that you use @artela/aspect-tool. The tool offers functionality to create Aspect development scaffolding and seamlessly integrates with the Artela Blockchain.