# What Is AssemblyScript and How Is It Used for Amadeus Contracts?

> Discover AssemblyScript, a TypeScript-like language for WebAssembly. Learn how Amadeus developers use it to write efficient blockchain smart contracts with familiar syntax.

- Repository: [Amadeus Protocol/node](https://github.com/amadeusprotocol/node)
- Tags: deep-dive
- Published: 2026-08-20

---

**AssemblyScript is a TypeScript-like language that compiles to WebAssembly, enabling Amadeus developers to write blockchain smart contracts with familiar syntax while producing fast, compact Wasm binaries.**

The Amadeus protocol leverages AssemblyScript as its primary smart contract language. In the `amadeusprotocol/node` repository, contracts are authored in `.ts` files, compiled to `.wasm` modules, and executed within the node's WebAssembly runtime. This approach combines the ergonomics of TypeScript with the performance and determinism required for blockchain consensus.

## Understanding AssemblyScript in the Amadeus Ecosystem

**AssemblyScript** strictly compiles a TypeScript subset to WebAssembly (Wasm), avoiding JavaScript's dynamic features in favor of static types and predictable memory layout. For Amadeus, this translates to contracts that are:

- **Deterministic** — required for replicated state machines
- **Compact** — small binary size reduces storage and bandwidth costs
- **Fast** — near-native execution speed via Wasm runtime
- **Familiar** — TypeScript syntax lowers the learning curve

The Amadeus node implements a **host environment** in Elixir ([`ex/lib/api/api_contract.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/api/api_contract.ex)) that exposes blockchain operations—logging, key-value storage, and cross-contract calls—as imports callable from Wasm modules.

## The AssemblyScript SDK Architecture

Amadeus provides a dedicated SDK located at [`contract_samples/assemblyscript/sdk.ts`](https://github.com/amadeusprotocol/node/blob/main/contract_samples/assemblyscript/sdk.ts) that abstracts the low-level host imports into developer-friendly TypeScript functions.

### Core SDK Components

| Component | Location | Purpose |
|-----------|----------|---------|
| **Host import wrappers** | [`sdk.ts`](https://github.com/amadeusprotocol/node/blob/main/sdk.ts) | Wrap `import_log`, `import_kv_put`, `import_call`, etc. with automatic encoding/decoding |
| **Memory helpers** | [`sdk.ts`](https://github.com/amadeusprotocol/node/blob/main/sdk.ts) | `memory_read_string`, `memory_read_bytes` for argument extraction |
| **Serialization utilities** | [`sdk.ts`](https://github.com/amadeusprotocol/node/blob/main/sdk.ts) | `bToI64`, `coin_raw`, `b58` for binary data handling |
| **Return mechanism** | [`sdk.ts`](https://github.com/amadeusprotocol/node/blob/main/sdk.ts) | `sdk.ret()` for passing results back to the caller |

The SDK functions manage memory allocation, convert between AssemblyScript types and the node's binary interface, and ensure proper cleanup—shielding contract authors from Wasm's low-level details.

## Writing and Compiling Amadeus Contracts

### Step 1: Implement Contract Entry Points

A minimal contract defines exported functions that the node invokes. Here's the canonical counter example from [`contract_samples/assemblyscript/0_counter.ts`](https://github.com/amadeusprotocol/node/blob/main/contract_samples/assemblyscript/0_counter.ts):

```typescript
import * as sdk from "./sdk";

export function init(): void {
  sdk.log("Init called during deployment of contract");
  sdk.kv_put("inited", "true");
}

export function get(): void {
  let cur_counter = sdk.bToI64(sdk.kv_get("the_counter"));
  sdk.ret(cur_counter);
}

export function increment(amount_ptr: i32): void {
  let amount = sdk.memory_read_string(amount_ptr);
  sdk.kv_increment("the_counter", amount);
  let incremented_counter = sdk.kv_increment("the_counter", 1);
  sdk.ret(incremented_counter);
}

```

Key patterns demonstrated:

- **`init()`** — runs once at deployment, initializes state
- **`sdk.kv_put` / `sdk.kv_get`** — persistent key-value storage
- **`sdk.kv_increment`** — atomic numeric operations
- **`sdk.ret`** — return values to the caller
- **`amount_ptr: i32`** — pointer-based argument passing (Wasm convention)

### Step 2: Cross-Contract Calls

The same file shows how contracts invoke each other:

```typescript
export function increment_another_counter(contract_ptr: i32): void {
  let contract = sdk.memory_read_bytes(contract_ptr);
  let incr_by = 3;
  sdk.log(`Calling increment on ${sdk.b58(contract)} by ${incr_by}`);
  let other_counter = sdk.call(contract, "increment", [sdk.b(incr_by)]);
  sdk.ret(other_counter);
}

```

This pattern uses **`sdk.call`** with the target contract address, method name, and serialized arguments array.

### Step 3: Compile with the Build Script

The repository includes [`contract_samples/assemblyscript/build_and_validate.sh`](https://github.com/amadeusprotocol/node/blob/main/contract_samples/assemblyscript/build_and_validate.sh) to handle compilation flags:

```bash

# From build_and_validate.sh

asc assembly/$1.ts \
  --target release \
  --use abort=doom \
  --runtime stub \
  --exportRuntime \
  -O3 \
  -o assembly/$1.wasm

```

This invokes the AssemblyScript compiler (`asc`) with optimizations enabled and the minimal runtime, producing the deployable Wasm binary.

## Deploying and Executing Contracts

Once compiled, contracts interact with the Amadeus testnet through CLI commands shown in the repository README:

```bash

# Deploy the compiled Wasm

Testnet.deploy "/path/to/contract_samples/assemblyscript/counter.wasm"

# Query the current counter value

Testnet.call sk, pk, "get", []

# Increment by a specific amount

Testnet.call sk, pk, "increment", ["2"]

```

The node handles:

1. **Module loading** — validates and instantiates the Wasm binary
2. **Symbol registration** — exposes exported functions as callable methods
3. **Transaction routing** — matches incoming calls to the appropriate entry point
4. **State isolation** — provides each contract with its own KV namespace
5. **Gas metering** — tracks execution cost for consensus

## Host Import Implementation

The bridge between Wasm and the blockchain is implemented in [`ex/lib/api/api_contract.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/api/api_contract.ex). Key imports available to AssemblyScript contracts include:

| Import | SDK Wrapper | Function |
|--------|-------------|----------|
| `import_log` | `sdk.log` | Debug logging |
| `import_kv_put` | `sdk.kv_put` / `sdk.kv_increment` | Persistent storage writes |
| `import_kv_get` | `sdk.kv_get` | Storage reads |
| `import_call` | `sdk.call` | Cross-contract invocation |
| `import_ret` | `sdk.ret` | Return data to caller |

These imports operate on linear memory shared between the Wasm runtime and the host, with the SDK handling pointer arithmetic and encoding.

## Why AssemblyScript for Amadeus?

Compared to alternatives, the Amadeus AssemblyScript approach offers:

- **Familiar toolchain** — npm-based, TypeScript-compatible IDE support
- **Deterministic output** — same source always produces identical Wasm
- **Minimal overhead** — no garbage collector in the default runtime, predictable performance
- **Small bundle size** — contracts measured in kilobytes, not megabytes
- **Auditable binaries** — Wasm is easier to formally verify than high-level bytecode

The `b58` encoding utilities and raw byte operations in [`sdk.ts`](https://github.com/amadeusprotocol/node/blob/main/sdk.ts) also reflect blockchain-native requirements without forcing developers into unfamiliar paradigms.

## Summary

- **AssemblyScript** compiles TypeScript to WebAssembly for Amadeus smart contracts
- The **SDK in [`sdk.ts`](https://github.com/amadeusprotocol/node/blob/main/sdk.ts)** wraps host imports for storage, logging, and cross-contract calls
- Contracts export entry points (`init`, `get`, `increment`) that the node invokes via Wasm runtime
- **[`build_and_validate.sh`](https://github.com/amadeusprotocol/node/blob/main/build_and_validate.sh)** automates compilation with optimization flags
- **Host imports** in [`ex/lib/api/api_contract.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/api/api_contract.ex) provide the blockchain bridge
- Deployment uses `Testnet.deploy` and `Testnet.call` commands against the compiled `.wasm` file

## Frequently Asked Questions

### What makes AssemblyScript different from regular TypeScript?

AssemblyScript is a strict subset of TypeScript that compiles directly to WebAssembly rather than JavaScript. It requires explicit types, lacks dynamic features like `any`, and produces standalone binary modules. For Amadeus, this ensures deterministic execution and eliminates JavaScript engine dependencies.

### How does the Amadeus node execute AssemblyScript contracts?

The node loads the `.wasm` binary into a WebAssembly runtime, registers exported functions as callable contract methods, and invokes them when processing transactions. Host imports in [`ex/lib/api/api_contract.ex`](https://github.com/amadeusprotocol/node/blob/main/ex/lib/api/api_contract.ex) give contracts access to blockchain state and operations.

### Can I use npm packages in Amadeus AssemblyScript contracts?

Only packages compatible with AssemblyScript's strict type system and standard library. Most npm packages targeting Node.js or browsers will not compile. The Amadeus SDK ([`sdk.ts`](https://github.com/amadeusprotocol/node/blob/main/sdk.ts)) provides the primary dependencies needed for contract development.

### Where can I find example Amadeus AssemblyScript contracts?

The repository includes [`contract_samples/assemblyscript/0_counter.ts`](https://github.com/amadeusprotocol/node/blob/main/contract_samples/assemblyscript/0_counter.ts), a complete example showing initialization, state management, arithmetic operations, and cross-contract calls. The [`build_and_validate.sh`](https://github.com/amadeusprotocol/node/blob/main/build_and_validate.sh) script demonstrates proper compilation flags.