-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support configurable constants contracts (#991)
- Loading branch information
1 parent
dcea59c
commit eda13d7
Showing
22 changed files
with
811 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@fuel-ts/abi-coder": minor | ||
"@fuel-ts/contract": minor | ||
--- | ||
|
||
support configurable constants for contracts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[project] | ||
authors = ["FuelLabs"] | ||
entry = "main.sw" | ||
license = "Apache-2.0" | ||
name = "echo-configurables" | ||
|
||
[dependencies] |
35 changes: 35 additions & 0 deletions
35
apps/docs-snippets/contracts/echo-configurables/src/main.sw
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// #region configurable-constants-1 | ||
contract; | ||
|
||
enum MyEnum { | ||
Checked: (), | ||
Pending: () | ||
} | ||
|
||
struct MyStruct { | ||
x: u8, | ||
y: u8, | ||
state: MyEnum | ||
} | ||
|
||
configurable { | ||
age: u8 = 25, | ||
tag: str[4] = "fuel", | ||
grades: [u8; 4] = [3, 4, 3, 2], | ||
my_struct: MyStruct = MyStruct { | ||
x: 1, | ||
y: 2, | ||
state: MyEnum::Pending | ||
} | ||
} | ||
|
||
abi EchoConfigurables { | ||
fn echo_configurables() -> (u8, str[4], [u8; 4], MyStruct); | ||
} | ||
|
||
impl EchoConfigurables for Contract { | ||
fn echo_configurables() -> (u8, str[4], [u8; 4], MyStruct) { | ||
(age, tag, grades, my_struct) | ||
} | ||
} | ||
// #endregion configurable-constants-1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 89 additions & 0 deletions
89
apps/docs-snippets/src/guide/contracts/configurable-constants.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import type { WalletUnlocked } from 'fuels'; | ||
import { ContractFactory } from 'fuels'; | ||
|
||
import { getSnippetContractArtifacts, SnippetContractEnum } from '../../../contracts'; | ||
import { getTestWallet } from '../../utils'; | ||
|
||
describe(__filename, () => { | ||
let wallet: WalletUnlocked; | ||
|
||
const { abi, bin } = getSnippetContractArtifacts(SnippetContractEnum.ECHO_CONFIGURABLES); | ||
|
||
const defaultValues = { | ||
age: 25, | ||
tag: 'fuel', | ||
grades: [3, 4, 3, 2], | ||
my_struct: { | ||
x: 1, | ||
y: 2, | ||
state: 'Pending', | ||
}, | ||
}; | ||
|
||
beforeAll(async () => { | ||
wallet = await getTestWallet(); | ||
}); | ||
|
||
it('should successfully set new values for all configurable constants', async () => { | ||
// #region configurable-constants-2 | ||
const configurableConstants: typeof defaultValues = { | ||
age: 30, | ||
tag: 'leuf', | ||
grades: [10, 9, 8, 9], | ||
my_struct: { | ||
x: 11, | ||
y: 22, | ||
state: 'Checked', | ||
}, | ||
}; | ||
|
||
const factory = new ContractFactory(bin, abi, wallet); | ||
|
||
const contract = await factory.deployContract({ | ||
configurableConstants, | ||
}); | ||
// #endregion configurable-constants-2 | ||
|
||
const { value } = await contract.functions.echo_configurables().get(); | ||
|
||
expect(value[0]).toEqual(configurableConstants.age); | ||
expect(value[1]).toEqual(configurableConstants.tag); | ||
expect(value[2]).toStrictEqual(configurableConstants.grades); | ||
expect(value[3]).toStrictEqual(configurableConstants.my_struct); | ||
}); | ||
|
||
it('should successfully set new value for one configurable constant', async () => { | ||
// #region configurable-constants-3 | ||
const configurableConstants = { | ||
age: 10, | ||
}; | ||
|
||
const factory = new ContractFactory(bin, abi, wallet); | ||
|
||
const contract = await factory.deployContract({ | ||
configurableConstants, | ||
}); | ||
// #endregion configurable-constants-3 | ||
|
||
const { value } = await contract.functions.echo_configurables().get(); | ||
|
||
expect(value[0]).toEqual(configurableConstants.age); | ||
expect(value[1]).toEqual(defaultValues.tag); | ||
expect(value[2]).toEqual(defaultValues.grades); | ||
expect(value[3]).toEqual(defaultValues.my_struct); | ||
}); | ||
|
||
it('should throw when not properly setting new values for structs', async () => { | ||
// #region configurable-constants-4 | ||
const configurableConstants = { | ||
my_struct: { | ||
x: 2, | ||
}, | ||
}; | ||
|
||
const factory = new ContractFactory(bin, abi, wallet); | ||
|
||
await expect(factory.deployContract({ configurableConstants })).rejects.toThrowError(); | ||
// #endregion configurable-constants-4 | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Configurable Constants | ||
|
||
Sway introduces a powerful feature: configurable constants. When creating a contract, you can define constants, each assigned with a default value. | ||
|
||
Before deploying the contract, you can then redefine the value for these constants, it can be all of them or as many as you need. | ||
|
||
This feature provides flexibility for dynamic contract environments. It allows a high level of customization, leading to more efficient and adaptable smart contracts. | ||
|
||
## Defining Configurable Constants | ||
|
||
Below is an example of a contract in which we declare four configurable constants: | ||
|
||
<<< @/../../docs-snippets/contracts/echo-configurables/src/main.sw#configurable-constants-1{rust:line-numbers} | ||
|
||
In this contract, we have a function `echo_configurables` that returns the values of the configurable constants. | ||
|
||
If each of these constants has new values that have been assigned to them, the function will return the updated values. Otherwise, the function will return the default values. | ||
|
||
## Setting New Values For Configurable Constants | ||
|
||
During contract deployment, you can define new values for the configurable constants. This is achieved as follows: | ||
|
||
<<< @/../../docs-snippets/src/guide/contracts/configurable-constants.test.ts#configurable-constants-2{ts:line-numbers} | ||
|
||
You can assign new values to any of these configurable constants. | ||
|
||
If you wish to assign a new value to just one constant, you can do the following: | ||
|
||
<<< @/../../docs-snippets/src/guide/contracts/configurable-constants.test.ts#configurable-constants-3{ts:line-numbers} | ||
|
||
Please note that when assigning new values for a `Struct`, all properties of the `Struct` must be defined. Failing to do so will result in an error: | ||
|
||
<<< @/../../docs-snippets/src/guide/contracts/configurable-constants.test.ts#configurable-constants-4{ts:line-numbers} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,48 @@ | ||
import { isPointerType } from './json-abi'; | ||
import { jsonFlatAbiMock } from '../test/fixtures/mocks'; | ||
|
||
import type { JsonAbiFragmentType } from './json-abi'; | ||
import { ABI, isPointerType } from './json-abi'; | ||
|
||
describe('JSON ABI', () => { | ||
afterEach(jest.restoreAllMocks); | ||
|
||
it.each(['u8', 'u16', 'u32', 'u64', 'bool'])( | ||
`should return false when it's not reference type`, | ||
(type) => { | ||
expect(isPointerType(type)).toBeFalsy(); | ||
} | ||
); | ||
|
||
it.each(['str[3]', 'b256', '[str[3]; 3]', 'struct MyStruct', 'enum MyEnum'])( | ||
`should return true when it's reference type`, | ||
(type) => { | ||
expect(isPointerType(type)).toBeTruthy(); | ||
} | ||
); | ||
|
||
it('should ensure `unflattenConfigurables` adds `fragmentType` to each `configurables` entry', () => { | ||
const abi = new ABI(jsonFlatAbiMock); | ||
|
||
const mockedValue: JsonAbiFragmentType = { | ||
type: 'dummy', | ||
name: 'dummy', | ||
components: null, | ||
typeArguments: null, | ||
}; | ||
|
||
const spy = jest.spyOn(abi, 'parseInput').mockReturnValue(mockedValue); | ||
|
||
const result = abi.unflattenConfigurables(); | ||
|
||
const expected1 = { ...abi.configurables[0], fragmentType: mockedValue }; | ||
const expected2 = { ...abi.configurables[1], fragmentType: mockedValue }; | ||
|
||
expect(result[0]).toStrictEqual(expected1); | ||
expect(result[1]).toStrictEqual(expected2); | ||
|
||
expect(spy).toHaveBeenCalledWith(jsonFlatAbiMock.configurables[0].configurableType); | ||
expect(spy).toHaveBeenCalledWith(jsonFlatAbiMock.configurables[1].configurableType); | ||
|
||
expect(spy).toHaveBeenCalledTimes(2); | ||
}); | ||
}); |
Oops, something went wrong.