Enums
Sway Enums are a little distinct from TypeScript Enums. In this document, we will explore how you can represent Sway Enums in the SDK and how to use them with Sway contract functions.
Basic Sway Enum Example
Consider the following basic Sway Enum called StateError
:
pub enum StateError {
Void: (),
Pending: (),
Completed: (),
}
The type ()
indicates that there is no additional data associated with each Enum variant. Sway allows you to create Enums of Enums or associate types with Enum variants.
Using Sway Enums As Function Parameters
Let's define a Sway contract function that takes a StateError
Enum variant as an argument and returns it:
fn echo_state_error_enum(state_error: StateError) -> StateError {
state_error
}
To execute the contract function and validate the response, we can use the following code:
import { StateErrorInput } from '../path/to/typegen/contracts/EchoEnum';
const enumVariant = StateErrorInput.Completed;
const { value } = await contract.functions.echo_state_error_enum(enumVariant).simulate();
expect(value).toEqual(enumVariant);
In this example, we simply pass the Enum variant as a value to execute the contract function call.
Enum of Enums Example
In this example, the Error
Enum is an Enum of two other Enums: StateError
and UserError
.
pub enum StateError {
Void: (),
Pending: (),
Completed: (),
}
pub enum UserError {
Unauthorized: (),
InsufficientPermissions: (),
}
pub enum Error {
StateError: StateError,
UserError: UserError,
}
Using Enums of Enums with Contract Functions
Now, let's create a Sway contract function that accepts any variant of the Error
Enum as a parameter and returns it immediately. This variant could be from either the StateError
or UserError
Enums.
fn echo_error_enum(error: Error) -> Error {
error
}
Since the Error
Enum is an Enum of Enums, we need to pass the function parameter differently. The parameter will be a TypeScript object:
import { UserErrorInput } from '../path/to/typegen/contracts/EchoEnum';
const enumParam = { UserError: UserErrorInput.InsufficientPermissions };
const { value } = await contract.functions.echo_error_enum(enumParam).simulate();
expect(value).toEqual(enumParam);
In this case, since the variant InsufficientPermissions
belongs to the UserError
Enum, we create a TypeScript object using the Enum name as the object key and the variant as the object value.
We would follow the same approach if we intended to use a variant from the StateError
Enum:
import { StateErrorInput } from '../path/to/typegen/contracts/EchoEnum';
const enumParam = { StateError: StateErrorInput.Completed };
const { value } = await contract.functions.echo_error_enum(enumParam).simulate();
expect(value).toEqual(enumParam);
Errors
While working with enums, you may run into the following issues:
Using an invalid enum type
Thrown when the type being passed to the enum does not match that expected by it.
// Valid types: string
const emumValue: number = 1;
await expectToThrowFuelError(
// @ts-expect-error number is not a valid type
() => contract.functions.echo_state_error_enum(emumValue).simulate(),
new FuelError(FuelError.CODES.INVALID_DECODE_VALUE, 'A field for the case must be provided.')
);
Using an invalid enum value
Thrown when the parameter passed is not an expected enum value.
// Valid values: 'Void', 'Pending', 'Completed'
const emumValue = 'NotStateEnumValue';
await expectToThrowFuelError(
// @ts-expect-error NotStateEnumValue is not a valid value
() => contract.functions.echo_state_error_enum(emumValue).simulate(),
new FuelError(FuelError.CODES.INVALID_DECODE_VALUE, 'Only one field must be provided.')
);
Using an invalid enum case key
Thrown when the passed enum case is not an expected enum case value.
// Valid case keys: 'StateError', 'UserError'
const enumParam = { UnknownKey: 'Completed' };
await expectToThrowFuelError(
// @ts-expect-error UnknownKey is not a valid key
() => contract.functions.echo_error_enum(enumParam).simulate(),
new FuelError(
FuelError.CODES.INVALID_DECODE_VALUE,
`Invalid case 'UnknownKey'. Valid cases: 'StateError', 'UserError'.`
)
);