Skip to main content

String - Dynamic Text Type

The Str type represents dynamic, UTF-8 encoded text data in AssemblyScript Stylus smart contracts. It provides basic string operations essential for text handling and display in smart contracts.

Import

import { Str, StrFactory } from '@as-stylus/as-stylus';

Overview

Str provides:

  • UTF-8 encoded text representation
  • Basic string creation and manipulation
  • Length operations for string measurements
  • Slice operation for substring extraction
  • String conversion capabilities

Available Operations

Based on the available transformers, Str supports these operations:

Factory Methods

  • StrFactory.create(): Str - Create new Str instance (empty)
  • StrFactory.fromString(value: string): Str - Create from string literal

Core Operations

  • .toString(): string - Convert to native string representation
  • .slice(start: U256, length: U256): string - Extract substring
  • Automatic conversion for return values

Creation and Basic Usage

Creating String Values

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck

import { Str, StrFactory } from '@as-stylus/as-stylus';

// Create empty string
const empty = StrFactory.create();

// Create from string literal
const greeting = StrFactory.fromString("Hello, World!");
const message = StrFactory.fromString("Contract initialized successfully");

// Create short strings
const symbol = StrFactory.fromString("ETH");
const name = StrFactory.fromString("Ethereum");

Basic Operations

const text = StrFactory.fromString("Hello, Blockchain!");

// Convert to native string
const nativeStr = text.toString(); // "Hello, Blockchain!"

// Extract substring using slice
const hello = text.slice(U256Factory.create(), U256Factory.fromString("5")); // "Hello"
const blockchain = text.slice(U256Factory.fromString("7"), U256Factory.fromString("10")); // "Blockchain"

String Manipulation Patterns

Basic Text Processing

function truncateString(input: Str, maxLength: U256): Str {
const inputStr = input.toString();
const maxLengthNum = parseInt(maxLength.toString());

if (inputStr.length <= maxLengthNum) {
return input;
}

return StrFactory.fromString(inputStr.substring(0, maxLengthNum));
}

function isEmpty(input: Str): boolean {
return input.toString().length == 0;
}

function getStringLength(input: Str): U256 {
const length = input.toString().length;
return U256Factory.fromString(length.toString());
}

String Validation

function validateTokenSymbol(symbol: string): boolean {
// Check length (typically 3-5 characters)
if (symbol.length < 3 || symbol.length > 5) {
return false;
}

return true;
}

function isValidLength(input: string, minLength: number, maxLength: number): boolean {
return input.length >= minLength && input.length <= maxLength;
}

function requireNonEmpty(input: string, fieldName: string): void {
if (input.length == 0) {
EmptyStringNotAllowed.revert(StrFactory.fromString(fieldName));
}
}

String Registry

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck

@Contract
export class NameRegistry {
static names: Mapping<Address, Str> = new Mapping<Address, Str>();
static addresses: Mapping<Str, Address> = new Mapping<Str, Address>();

@External
static registerName(name: string): void {
requireNonEmpty(name, "name");

if (name.length > 32) {
const nameStr = StrFactory.fromString(name);
InvalidStringLength.revert(nameStr, U256Factory.fromString("32"));
}

const caller = msg.sender;
const nameStr = StrFactory.fromString(name);

// Check if name is already taken
const existingAddr = addresses.get(nameStr);
if (!existingAddr.isZero()) {
// Name already taken
return;
}

// Register name
names.set(caller, nameStr);
addresses.set(nameStr, caller);

NameChanged.emit(nameStr);
}

@View
static resolveName(name: string): Address {
const nameStr = StrFactory.fromString(name);
return addresses.get(nameStr);
}

@View
static getNameOf(addr: Address): string {
return names.get(addr);
}

@View
static isNameTaken(name: string): boolean {
const nameStr = StrFactory.fromString(name);
const addr = addresses.get(nameStr);
return !addr.isZero();
}
}

Error Handling

// Validation function with custom errors
function requireStringLength(input: string, minLen: number, maxLen: number): void {
if (input.length < minLen || input.length > maxLen) {
const inputStr = StrFactory.fromString(input);
const maxLengthU256 = U256Factory.fromString(maxLen.toString());
InvalidStringLength.revert(inputStr, maxLengthU256);
}
}

function requireNonEmptyField(input: string, fieldName: string): void {
if (input.length == 0) {
const fieldStr = StrFactory.fromString(fieldName);
EmptyStringNotAllowed.revert(fieldStr);
}
}

Best Practices

Do

  • Use StrFactory.fromString() to create strings from literals
  • Validate length before storing
  • Use native strings for validation logic
  • Convert to Str only for storage
  • Validate inputs before processing

Avoid

  • Storing extremely long strings
  • Not validating input length
  • Multiple unnecessary conversions
  • Complex string operations in contracts