Skip to content

Commit

Permalink
Merge branch 'master' into st/fix/witness-entry-for-predicates
Browse files Browse the repository at this point in the history
  • Loading branch information
Torres-ssf committed May 8, 2024
2 parents d5f64fd + d0e9b1a commit 8dbaf27
Show file tree
Hide file tree
Showing 41 changed files with 1,185 additions and 248 deletions.
2 changes: 2 additions & 0 deletions .changeset/famous-olives-shake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
5 changes: 5 additions & 0 deletions .changeset/large-masks-warn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fuel-ts/abi-typegen": patch
---

feat: support `Result<T, E>` type in typegen
2 changes: 2 additions & 0 deletions .changeset/shaggy-cougars-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
2 changes: 2 additions & 0 deletions .changeset/twelve-insects-act.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
3 changes: 2 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
interval: "weekly"
day: "sunday"
open-pull-requests-limit: 10
labels:
- "chore"
Expand Down
17 changes: 17 additions & 0 deletions .github/workflows/pr-lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ jobs:
# e.g. when a script is added in the scripts folder
exit 0
fi
echo "CHANGESET_FILE=$(echo "$CHANGESET_FILE")" >> $GITHUB_ENV
AFFECTED_PACKAGES=$(sed -n '/---/,/---/p' "$CHANGESET_FILE" | sed '/---/d')
Expand All @@ -104,6 +105,22 @@ jobs:
env:
PR_TITLE: ${{ github.event.pull_request.title }}

- name: Validate added changeset will be deleted
if: ${{ env.CHANGESET_FILE != '' }}
run: |
pnpm changeset version
if git status --porcelain .changeset | grep -q "D $CHANGESET_FILE"; then
git reset --hard
exit 0
fi
# Throw if changeset not in deleted changesets
echo "Changeset file $CHANGESET_FILE will not get deleted in the changesets PR. Check its affected packages."
exit 1
env:
CHANGESET_FILE: ${{ env.CHANGESET_FILE }}

- name: Validate that there are only patch changes
if: startsWith(github.base_ref, 'release/')
run: |
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ jobs:
e2e:
runs-on: ubuntu-latest
timeout-minutes: 10
needs: [environments]
if: ${{ !github.event.pull_request.draft }}
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
1 change: 1 addition & 0 deletions packages/abi-typegen/src/abi/Abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export class Abi {
option: 'Option',
enum: 'Enum',
vector: 'Vec',
result: 'Result',
};

this.commonTypesInUse = [];
Expand Down
2 changes: 1 addition & 1 deletion packages/abi-typegen/src/abi/types/EnumType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class EnumType extends AType implements IType {
public name = 'enum';

static MATCH_REGEX: RegExp = /^enum (.+)$/m;
static IGNORE_REGEX: RegExp = /^enum Option$/m;
static IGNORE_REGEX: RegExp = /^enum (Option|Result)$/m;

static isSuitableFor(params: { type: string }) {
const isAMatch = EnumType.MATCH_REGEX.test(params.type);
Expand Down
40 changes: 40 additions & 0 deletions packages/abi-typegen/src/abi/types/ResultType.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {
AbiTypegenProjectsEnum,
getTypegenForcProject,
} from '../../../test/fixtures/forc-projects/index';
import type { IRawAbiTypeRoot } from '../../index';
import { parseTypes } from '../../utils/parseTypes';

import { EnumType } from './EnumType';
import { ResultType } from './ResultType';

/**
* @group node
*/
describe('ResultType.ts', () => {
/*
Test helpers
*/
function getResultType() {
const project = getTypegenForcProject(AbiTypegenProjectsEnum.FULL);
const rawTypes = project.abiContents.types as IRawAbiTypeRoot[];
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return parseTypes({ rawAbiTypes: [rawTypes.find((t) => t.type === 'enum Result')!] })[0];
}

test('should properly evaluate type suitability', () => {
const suitableForResult = ResultType.isSuitableFor({ type: ResultType.swayType });
const suitableForEnum = ResultType.isSuitableFor({ type: EnumType.swayType });

expect(suitableForResult).toEqual(true);
expect(suitableForEnum).toEqual(false);
});

test('should properly parse type attributes', () => {
const type = getResultType();

expect(type.attributes.inputLabel).toEqual('Result');
expect(type.attributes.outputLabel).toEqual('Result');
expect(type.requiredFuelsMembersImports).toStrictEqual([]);
});
});
23 changes: 23 additions & 0 deletions packages/abi-typegen/src/abi/types/ResultType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { IType } from '../../types/interfaces/IType';

import { AType } from './AType';

export class ResultType extends AType implements IType {
public static swayType = 'enum Result';

public name = 'result';

static MATCH_REGEX: RegExp = /^enum Result$/m;

static isSuitableFor(params: { type: string }) {
return ResultType.MATCH_REGEX.test(params.type);
}

public parseComponentsAttributes(_params: { types: IType[] }) {
this.attributes = {
inputLabel: `Result`,
outputLabel: `Result`,
};
return this.attributes;
}
}
6 changes: 6 additions & 0 deletions packages/abi-typegen/src/templates/common/common.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ export type Enum<T> = {
export type Option<T> = T | undefined;

export type Vec<T> = T[];

/**
* Mimics Sway Result enum type.
* Ok represents the success case, while Err represents the error case.
*/
export type Result<T, E> = Enum<{Ok: T, Err: E}>;
2 changes: 1 addition & 1 deletion packages/abi-typegen/src/utils/supportedTypes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ import { supportedTypes } from './supportedTypes';
*/
describe('supportedTypes.ts', () => {
test('should export all supported types', () => {
expect(supportedTypes.length).toEqual(23);
expect(supportedTypes.length).toEqual(24);
});
});
2 changes: 2 additions & 0 deletions packages/abi-typegen/src/utils/supportedTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { GenericType } from '../abi/types/GenericType';
import { OptionType } from '../abi/types/OptionType';
import { RawUntypedPtr } from '../abi/types/RawUntypedPtr';
import { RawUntypedSlice } from '../abi/types/RawUntypedSlice';
import { ResultType } from '../abi/types/ResultType';
import { StdStringType } from '../abi/types/StdStringType';
import { StrSliceType } from '../abi/types/StrSliceType';
import { StrType } from '../abi/types/StrType';
Expand Down Expand Up @@ -46,4 +47,5 @@ export const supportedTypes = [
U8Type,
VectorType,
EvmAddressType,
ResultType,
];
24 changes: 24 additions & 0 deletions packages/abi-typegen/test/fixtures/forc-projects/full/src/main.sw
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ struct StructWithSingleOption {
single: Option<StructWithMultiOption>,
}

enum MyContractError {
DivisionByZero: (),
}

fn divide(numerator: u64, denominator: u64) -> Result<u64, MyContractError> {
if (denominator == 0) {
return Err(MyContractError::DivisionByZero);
} else {
Ok(numerator / denominator)
}
}

abi MyContract {
fn types_empty(x: ()) -> ();
fn types_empty_then_value(x: (), y: u8) -> ();
Expand Down Expand Up @@ -52,6 +64,7 @@ abi MyContract {
fn types_bytes(x: Bytes) -> Bytes;
fn types_raw_slice(x: raw_slice) -> raw_slice;
fn types_std_string(x: String) -> String;
fn types_result(x: Result<u64, u32>) -> Result<u64, str[10]>;
}

impl MyContract for Contract {
Expand Down Expand Up @@ -137,4 +150,15 @@ impl MyContract for Contract {
fn types_std_string(x: String) -> String {
x
}
fn types_result(x: Result<u64, u32>) -> Result<u64, str[10]> {
if (x.is_err()) {
return Err(__to_str_array("InputError"));
}

let result = divide(20, x.unwrap());
match result {
Ok(value) => Ok(value),
Err(MyContractError::DivisionByZero) => Err(__to_str_array("DivisError")),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import type {
StdString,
} from 'fuels';

import type { Option, Enum, Vec } from "./common";
import type { Option, Enum, Vec, Result } from "./common";

export enum MyEnumInput { Checked = 'Checked', Pending = 'Pending' };
export enum MyEnumOutput { Checked = 'Checked', Pending = 'Pending' };
Expand Down Expand Up @@ -53,6 +53,7 @@ interface MyContractAbiInterface extends Interface {
types_option: FunctionFragment;
types_option_geo: FunctionFragment;
types_raw_slice: FunctionFragment;
types_result: FunctionFragment;
types_std_string: FunctionFragment;
types_str: FunctionFragment;
types_struct: FunctionFragment;
Expand Down Expand Up @@ -82,6 +83,7 @@ interface MyContractAbiInterface extends Interface {
encodeFunctionData(functionFragment: 'types_option', values: [Option<BigNumberish>]): Uint8Array;
encodeFunctionData(functionFragment: 'types_option_geo', values: [Option<MyStructInput>]): Uint8Array;
encodeFunctionData(functionFragment: 'types_raw_slice', values: [RawSlice]): Uint8Array;
encodeFunctionData(functionFragment: 'types_result', values: [Result<BigNumberish, BigNumberish>]): Uint8Array;
encodeFunctionData(functionFragment: 'types_std_string', values: [StdString]): Uint8Array;
encodeFunctionData(functionFragment: 'types_str', values: [string]): Uint8Array;
encodeFunctionData(functionFragment: 'types_struct', values: [MyStructInput]): Uint8Array;
Expand Down Expand Up @@ -110,6 +112,7 @@ interface MyContractAbiInterface extends Interface {
decodeFunctionData(functionFragment: 'types_option', data: BytesLike): DecodedValue;
decodeFunctionData(functionFragment: 'types_option_geo', data: BytesLike): DecodedValue;
decodeFunctionData(functionFragment: 'types_raw_slice', data: BytesLike): DecodedValue;
decodeFunctionData(functionFragment: 'types_result', data: BytesLike): DecodedValue;
decodeFunctionData(functionFragment: 'types_std_string', data: BytesLike): DecodedValue;
decodeFunctionData(functionFragment: 'types_str', data: BytesLike): DecodedValue;
decodeFunctionData(functionFragment: 'types_struct', data: BytesLike): DecodedValue;
Expand Down Expand Up @@ -142,6 +145,7 @@ export class MyContractAbi extends Contract {
types_option: InvokeFunction<[x: Option<BigNumberish>], Option<number>>;
types_option_geo: InvokeFunction<[x: Option<MyStructInput>], Option<MyStructOutput>>;
types_raw_slice: InvokeFunction<[x: RawSlice], RawSlice>;
types_result: InvokeFunction<[x: Result<BigNumberish, BigNumberish>], Result<BN, string>>;
types_std_string: InvokeFunction<[x: StdString], StdString>;
types_str: InvokeFunction<[x: string], string>;
types_struct: InvokeFunction<[x: MyStructInput], MyStructOutput>;
Expand Down
Loading

0 comments on commit 8dbaf27

Please sign in to comment.