Skip to content

Commit

Permalink
Add Identity type to Sway Book (FuelLabs#2041)
Browse files Browse the repository at this point in the history
* Add Identity type to Sway Book

* Move Identity code to examples directory

* Add Forc.lock to gitignore

* Update docs/src/basics/blockchain_types.md

Co-authored-by: John Adler <[email protected]>

* Typo

* Ran forc fmt

* Update Cargo.toml

* Update examples/identity/src/main.sw

Co-authored-by: Mohammad Fawaz <[email protected]>

* Delete Cargo.toml

* Update Identity docs to use anchor

* Fix CI

* Add path to std in Forc.toml and update Forc.lock std source

* Run forc fmt again

Co-authored-by: John Adler <[email protected]>
Co-authored-by: Mohammad Fawaz <[email protected]>
  • Loading branch information
3 people authored Jun 20, 2022
1 parent 32b48c2 commit a8f8bb4
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 0 deletions.
32 changes: 32 additions & 0 deletions docs/src/basics/blockchain_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,35 @@ let my_number: b256 = 0x00000000000000000000000000000000000000000000000000000000
let my_contract_id: ContractId = ~ContractId::from(my_number);
let forty_two: b256 = my_contract_id.into();
```

## `Identity` Type

The `Identity` type is an enum that allows for the handling of both `Address` and `ContractId` types. This is useful in cases where either type is accepted, e.g. receiving funds from an identified sender, but not caring if the sender is an address or a contract.

An `Identity` is implemented as follows.

```sway
{{#include ../../../sway-lib-std/src/identity.sw:docs_identity}}
```

Casting to an `Identity` must be done explicitly:

```sway
{{#include ../../../examples/identity/src/main.sw:cast_to_identity}}
```

A `match` statement can be used to return to an `Address` or `ContractId` as well as handle cases in which their execution differs.

```sway
{{#include ../../../examples/identity/src/main.sw:identity_to_contract_id}}
```

```sway
{{#include ../../../examples/identity/src/main.sw:different_executions}}
```

A common use case for `Identity` is for access control. The use of `Identity` uniquely allows both `ContractId` and `Address` to have access control inclusively.

```sway
{{#include ../../../examples/identity/src/main.sw:access_control_with_identity}}
```
14 changes: 14 additions & 0 deletions examples/identity/Forc.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[[package]]
name = 'core'
source = 'path+from-root-C38E96E529F27BA9'
dependencies = []

[[package]]
name = 'identity'
source = 'root'
dependencies = ['std']

[[package]]
name = 'std'
source = 'path+from-root-C38E96E529F27BA9'
dependencies = ['core']
8 changes: 8 additions & 0 deletions examples/identity/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "identity"

[dependencies]
std = { path = "../../sway-lib-std" }
10 changes: 10 additions & 0 deletions examples/identity/src/abi.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
library abi;

use std::identity::Identity;

abi IdentityExample {
#[storage(read)]fn access_control_with_identity();
fn cast_to_identity();
fn different_executions(my_identity: Identity);
fn identity_to_contract_id(my_identity: Identity);
}
5 changes: 5 additions & 0 deletions examples/identity/src/errors.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
library errors;

pub enum MyError {
UnauthorizedUser: (),
}
68 changes: 68 additions & 0 deletions examples/identity/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
contract;

dep abi;
dep errors;

use abi::IdentityExample;
use errors::MyError;

use std::{
address::Address,
assert::require,
chain::auth::{AuthError, msg_sender},
constants::BASE_ASSET_ID,
contract_id::ContractId,
identity::*,
result::*,
revert::revert,
token::{force_transfer_to_contract, transfer_to_output}
};

storage {
owner: Identity,
}

impl IdentityExample for Contract {
fn cast_to_identity() {
// ANCHOR: cast_to_identity
let my_address: Address = ~Address::from(BASE_ASSET_ID);
let my_identity: Identity = Identity::Address(my_address);
// ANCHOR_END: cast_to_identity
}

fn identity_to_contract_id(my_identity: Identity) {
// ANCHOR: identity_to_contract_id
let my_contract_id: ContractId = match my_identity {
Identity::ContractId(identity) => {
identity
},
_ => {
revert(0);
}
};
// ANCHOR_END: identity_to_contract_ids
}

fn different_executions(my_identity: Identity) {
let amount = 1;
let token_id = ~ContractId::from(BASE_ASSET_ID);

// ANCHOR: different_executions
match my_identity {
Identity::Address(identity) => {
transfer_to_output(amount, token_id, identity);
},
Identity::ContractId(identity) => {
force_transfer_to_contract(amount, token_id, identity);
},
};
// ANCHOR_END: different_executions
}

#[storage(read)]fn access_control_with_identity() {
// ANCHOR: access_control_with_identity
let sender: Result<Identity, AuthError> = msg_sender();
require(sender.unwrap() == storage.owner, MyError::UnauthorizedUser);
// ANCHOR_END: access_control_with_identity
}
}
2 changes: 2 additions & 0 deletions sway-lib-std/src/identity.sw
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ library identity;
use ::address::Address;
use ::contract_id::ContractId;

// ANCHOR: docs_identity
pub enum Identity {
Address: Address,
ContractId: ContractId,
}
// ANCHOR_END: docs_identity

impl core::ops::Eq for Identity {
fn eq(self, other: Self) -> bool {
Expand Down

0 comments on commit a8f8bb4

Please sign in to comment.