Skip to content

Commit

Permalink
Update examples (#1450)
Browse files Browse the repository at this point in the history
* update examples and fix wording

* update `identity_iota` dependency in examples
  • Loading branch information
wulfraem authored Nov 27, 2024
1 parent b885b6e commit 40cb627
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 185 deletions.
117 changes: 56 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,12 @@ identity_iota = { version = "1.4.0" }
To try out the [examples](https://github.com/iotaledger/identity.rs/blob/HEAD/examples), you can also do this:

1. Clone the repository, e.g. through `git clone https://github.com/iotaledger/identity.rs`
2. Start IOTA Sandbox as described in the [next section](#example-creating-an-identity)
3. Run the example to create a DID using `cargo run --release --example 0_create_did`
2. Get the [IOTA binaries](https://github.com/iotaledger/iota/releases).
3. Start a local network for testing with `iota start --force-regenesis --with-faucet`.
4. Request funds with `iota client faucet`.
5. Publish a test identity package to your local network: `./identity_iota_core/scripts/publish_identity_package.sh`.
6. Get the `packageId` value from the output (the entry with `"type": "published"`) and pass this as `IDENTITY_IOTA_PKG_ID` env value.
7. Run the example to create a DID using `IDENTITY_IOTA_PKG_ID=(the value from previous step) run --release --example 0_create_did`

## Example: Creating an Identity

Expand All @@ -76,7 +80,7 @@ Test this example using https://github.com/anko/txm: `txm README.md`
!test program
cd ../..
mkdir tmp
cat | sed -e 's#identity_iota = { version = "[^"]*"#identity_iota = { path = "../identity_iota"#' > tmp/Cargo.toml
cat | sed -e 's#identity_iota = { git = "[^"]*"#identity_iota = { path = "../identity_iota"#' > tmp/Cargo.toml
echo '[workspace]' >>tmp/Cargo.toml
-->
<!-- !test check Cargo Example -->
Expand All @@ -88,8 +92,8 @@ version = "1.0.0"
edition = "2021"

[dependencies]
identity_iota = { version = "1.4.0", features = ["memstore"] }
iota-sdk = { version = "1.0.2", default-features = true, features = ["tls", "client", "stronghold"] }
identity_iota = { git = "https://github.com/iotaledger/identity.rs.git", tag = "v1.6.0-alpha", features = ["memstore"] }
iota-sdk = { git = "https://github.com/iotaledger/iota.git", package = "iota-sdk", tag = "v0.7.0-alpha" }
tokio = { version = "1", features = ["full"] }
anyhow = "1.0.62"
rand = "0.8.5"
Expand All @@ -111,76 +115,67 @@ timeout 360 cargo build || (echo "Process timed out after 360 seconds" && exit 1


```rust,no_run
use identity_iota::core::ToJson;
use identity_iota::iota::IotaClientExt;
use anyhow::Context;
use identity_iota::iota::IotaDocument;
use identity_iota::iota::IotaIdentityClientExt;
use identity_iota::iota::NetworkName;
use identity_iota::iota::rebased::client::convert_to_address;
use identity_iota::iota::rebased::client::get_sender_public_key;
use identity_iota::iota::rebased::client::IdentityClient;
use identity_iota::iota::rebased::client::IdentityClientReadOnly;
use identity_iota::iota::rebased::transaction::Transaction;
use identity_iota::storage::JwkDocumentExt;
use identity_iota::storage::JwkMemStore;
use identity_iota::storage::JwkStorage;
use identity_iota::storage::KeyIdMemstore;
use identity_iota::storage::KeyType;
use identity_iota::storage::Storage;
use identity_iota::storage::StorageSigner;
use identity_iota::verification::jws::JwsAlgorithm;
use identity_iota::verification::MethodScope;
use iota_sdk::client::api::GetAddressesOptions;
use iota_sdk::client::secret::stronghold::StrongholdSecretManager;
use iota_sdk::client::secret::SecretManager;
use iota_sdk::client::Client;
use iota_sdk::crypto::keys::bip39;
use iota_sdk::types::block::address::Bech32Address;
use iota_sdk::types::block::output::AliasOutput;
use iota_sdk::types::block::output::dto::AliasOutputDto;
use iota_sdk::IotaClientBuilder;
use tokio::io::AsyncReadExt;
// The endpoint of the IOTA node to use.
static API_ENDPOINT: &str = "http://localhost";
/// Demonstrates how to create a DID Document and publish it in a new Alias Output.
// Test budget for transactions.
const TEST_GAS_BUDGET: u64 = 50_000_000;
/// Demonstrates how to create a DID Document and publish it in a new identity.
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Create a new client to interact with the IOTA ledger.
let client: Client = Client::builder()
.with_primary_node(API_ENDPOINT, None)?
.finish()
let iota_client = IotaClientBuilder::default()
.build(API_ENDPOINT)
.await
.map_err(|err| anyhow::anyhow!(format!("failed to connect to network; {}", err)))?;
// Create new storage and generate new key.
let storage = Storage::new(JwkMemStore::new(), KeyIdMemstore::new());
let generate = storage
.key_storage()
.generate(KeyType::new("Ed25519"), JwsAlgorithm::EdDSA)
.await?;
// Create a new Stronghold.
let stronghold = StrongholdSecretManager::builder()
.password("secure_password".to_owned())
.build("./example-strong.hodl")?;
// Generate a mnemonic and store it in the Stronghold.
let random: [u8; 32] = rand::random();
let mnemonic =
bip39::wordlist::encode(random.as_ref(), &bip39::wordlist::ENGLISH).map_err(|err| anyhow::anyhow!("{err:?}"))?;
stronghold.store_mnemonic(mnemonic).await?;
// Create a new secret manager backed by the Stronghold.
let secret_manager: SecretManager = SecretManager::Stronghold(stronghold);
// Get the Bech32 human-readable part (HRP) of the network.
let network_name: NetworkName = client.network_name().await?;
// Get an address from the secret manager.
let address: Bech32Address = secret_manager
.generate_ed25519_addresses(
GetAddressesOptions::default()
.with_range(0..1)
.with_bech32_hrp((&network_name).try_into()?),
)
.await?[0];
println!("Your wallet address is: {}", address);
let public_key_jwk = generate.jwk.to_public().expect("public components should be derivable");
let public_key_bytes = get_sender_public_key(&public_key_jwk)?;
let sender_address = convert_to_address(&public_key_bytes)?;
let package_id = std::env::var("IDENTITY_IOTA_PKG_ID")
.map_err(|e| {
anyhow::anyhow!("env variable IDENTITY_IOTA_PKG_ID must be set in order to run the examples").context(e)
})
.and_then(|pkg_str| pkg_str.parse().context("invalid package id"))?;
// Create identity client with signing capabilities.
let read_only_client = IdentityClientReadOnly::new(iota_client, package_id).await?;
let signer = StorageSigner::new(&storage, generate.key_id, public_key_jwk);
let identity_client = IdentityClient::new(read_only_client, signer).await?;
println!("Your wallet address is: {}", sender_address);
println!("Please request funds from http://localhost/faucet/, wait for a couple of seconds and then press Enter.");
tokio::io::stdin().read_u8().await?;
// Create a new DID document with a placeholder DID.
// The DID will be derived from the Alias Id of the Alias Output after publishing.
let mut document: IotaDocument = IotaDocument::new(&network_name);
// Insert a new Ed25519 verification method in the DID document.
let storage: Storage<JwkMemStore, KeyIdMemstore> = Storage::new(JwkMemStore::new(), KeyIdMemstore::new());
document
let mut unpublished: IotaDocument = IotaDocument::new(identity_client.network());
let verification_method_fragment = unpublished
.generate_method(
&storage,
JwkMemStore::ED25519_KEY_TYPE,
Expand All @@ -190,13 +185,13 @@ async fn main() -> anyhow::Result<()> {
)
.await?;
// Construct an Alias Output containing the DID document, with the wallet address
// set as both the state controller and governor.
let alias_output: AliasOutput = client.new_did_output(address.into(), document, None).await?;
println!("Alias Output: {}", AliasOutputDto::from(&alias_output).to_json_pretty()?);
// Publish new DID document.
let document = identity_client
.publish_did_document(unpublished)
.execute(&identity_client)
.await?
.output;
// Publish the Alias Output and get the published DID document.
let document: IotaDocument = client.publish_did_output(&secret_manager, alias_output).await?;
println!("Published DID document: {:#}", document);
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion examples/0_basic/1_update_did.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use identity_iota::verification::jws::JwsAlgorithm;
use identity_iota::verification::MethodRelationship;
use identity_iota::verification::MethodScope;

/// Demonstrates how to update a DID document in an existing Alias Output.
/// Demonstrates how to update a DID document in an existing identity.
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// create new client to interact with chain and get funded account with keys
Expand Down
4 changes: 2 additions & 2 deletions examples/0_basic/2_resolve_did.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use examples::get_memstorage;
use identity_iota::iota::IotaDocument;
use identity_iota::prelude::Resolver;

/// Demonstrates how to resolve an existing DID in an Alias Output.
/// Demonstrates how to resolve an existing DID in an identity.
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// create new client to interact with chain and get funded account with keys
Expand All @@ -20,7 +20,7 @@ async fn main() -> anyhow::Result<()> {
let did = document.id().clone();

// We can resolve a `IotaDID` to bytes via client.
// Resolve the associated Alias Output and extract the DID document from it.
// Resolve the associated identity and extract the DID document from it.
let client_document: IotaDocument = identity_client.resolve_did(&did).await?;
println!("Client resolved DID Document: {client_document:#}");

Expand Down
6 changes: 3 additions & 3 deletions examples/0_basic/3_deactivate_did.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use examples::TEST_GAS_BUDGET;
use identity_iota::iota::IotaDID;
use identity_iota::iota::IotaDocument;

/// Demonstrates how to deactivate a DID in an Alias Output.
/// Demonstrates how to deactivate a DID in an identity.
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// create new client to interact with chain and get funded account with keys
Expand All @@ -23,8 +23,8 @@ async fn main() -> anyhow::Result<()> {
let did: IotaDID = document.id().clone();

// Deactivate the DID by publishing an empty document.
// This process can be reversed since the Alias Output is not destroyed.
// Deactivation may only be performed by the state controller of the Alias Output.
// This process can be reversed since the identity is not destroyed.
// Deactivation may only be performed by a controller of the identity.
identity_client.deactivate_did_output(&did, TEST_GAS_BUDGET).await?;

// Resolving a deactivated DID returns an empty DID document
Expand Down
30 changes: 1 addition & 29 deletions examples/1_advanced/10_zkp_revocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,33 +67,6 @@ use secret_storage::Signer;
use std::thread;
use std::time::Duration as SleepDuration;

// // Creates a DID with a JWP verification method.
// pub async fn create_did<K, I, S>(
// identity_client: &IdentityClient<S>,
// storage: &Storage<K, I>,
// key_type: KeyType,
// alg: ProofAlgorithm,
// ) -> anyhow::Result<(IotaDocument, String)>
// where
// K: identity_storage::JwkStorage + identity_storage::JwkStorageBbsPlusExt,
// I: identity_storage::KeyIdStorage,
// S: Signer<IotaKeySignature> + Sync,
// {
// // Create a new DID document with a placeholder DID.
// // The DID will be derived from the Alias Id of the Alias Output after publishing.
// let mut unpublished: IotaDocument = IotaDocument::new(identity_client.network());

// let verification_method_fragment = unpublished
// .generate_method_jwp(storage, key_type, alg, None, MethodScope::VerificationMethod)
// .await?;

// let document = identity_client
// .publish_did_document(unpublished)
// .execute_with_gas(TEST_GAS_BUDGET, identity_client)
// .await?;

// Ok((document, verification_method_fragment))
// }
async fn create_did<K, I, S>(
identity_client: &IdentityClient<S>,
storage: &Storage<K, I>,
Expand All @@ -110,7 +83,6 @@ where
let network_name: &NetworkName = identity_client.network();

// Create a new DID document with a placeholder DID.
// The DID will be derived from the Alias Id of the Alias Output after publishing.
let mut unpublished: IotaDocument = IotaDocument::new(network_name);

// New Verification Method containing a BBS+ key
Expand Down Expand Up @@ -147,7 +119,7 @@ where
Ok((document, fragment))
}

/// Demonstrates how to create an Anonymous Credential with BBS+.
/// Demonstrates how to revoke a credential.
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// ===========================================================================
Expand Down
4 changes: 2 additions & 2 deletions examples/1_advanced/4_identity_history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use identity_iota::iota::IotaDocument;
use identity_iota::verification::MethodRelationship;
use iota_sdk::rpc_types::IotaObjectData;

/// Demonstrates how to obtain the alias output history.
/// Demonstrates how to obtain the identity history.
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Create a new client to interact with the IOTA ledger.
Expand Down Expand Up @@ -53,7 +53,7 @@ async fn main() -> anyhow::Result<()> {
}

// ====================================
// Retrieving the Alias Output History
// Retrieving the identity History
// ====================================

// Step 1 - Get the latest identity
Expand Down
1 change: 0 additions & 1 deletion examples/1_advanced/9_zkp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ where
S: Signer<IotaKeySignature> + Sync,
{
// Create a new DID document with a placeholder DID.
// The DID will be derived from the Alias Id of the Alias Output after publishing.
let mut unpublished: IotaDocument = IotaDocument::new(identity_client.network());

let verification_method_fragment = unpublished
Expand Down
28 changes: 13 additions & 15 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,28 @@ cargo run --release --example 0_create_did

The following basic CRUD (Create, Read, Update, Delete) examples are available:

| Name | Information |
| :------------------------------------------------ | :----------------------------------------------------------------------------------- |
| [0_create_did](./0_basic/0_create_did.rs) | Demonstrates how to create a DID Document and publish it in a new Alias Output. |
| [1_update_did](./0_basic/1_update_did.rs) | Demonstrates how to update a DID document in an existing Alias Output. |
| [2_resolve_did](./0_basic/2_resolve_did.rs) | Demonstrates how to resolve an existing DID in an Alias Output. |
| [3_deactivate_did](./0_basic/3_deactivate_did.rs) | Demonstrates how to deactivate a DID in an Alias Output. |
| [4_delete_did](./0_basic/4_delete_did.rs) | Demonstrates how to delete a DID in an Alias Output, reclaiming the storage deposit. |
| [5_create_vc](./0_basic/5_create_vc.rs) | Demonstrates how to create and verify verifiable credentials. |
| [6_create_vp](./0_basic/6_create_vp.rs) | Demonstrates how to create and verify verifiable presentations. |
| [7_revoke_vc](./0_basic/7_revoke_vc.rs) | Demonstrates how to revoke a verifiable credential. |
| Name | Information |
| :------------------------------------------------------ | :----------------------------------------------------------------------------------- |
| [0_create_did](./0_basic/0_create_did.rs) | Demonstrates how to create a DID Document and publish it in a new identity. |
| [1_update_did](./0_basic/1_update_did.rs) | Demonstrates how to update a DID document in an existing identity. |
| [2_resolve_did](./0_basic/2_resolve_did.rs) | Demonstrates how to resolve an existing DID in an identity. |
| [3_deactivate_did](./0_basic/3_deactivate_did.rs) | Demonstrates how to deactivate a DID in an identity. |
| [5_create_vc](./0_basic/5_create_vc.rs) | Demonstrates how to create and verify verifiable credentials. |
| [6_create_vp](./0_basic/6_create_vp.rs) | Demonstrates how to create and verify verifiable presentations. |
| [7_revoke_vc](./0_basic/7_revoke_vc.rs) | Demonstrates how to revoke a verifiable credential. |
| [8_legacy_stronghold](./0_basic/8_legacy_stronghold.rs) | Demonstrates how to use stronghold for secure storage.. |

## Advanced Examples

The following advanced examples are available:

| Name | Information |
| :------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------- |
| [0_did_controls_did](./1_advanced/0_did_controls_did.rs) | Demonstrates how an identity can control another identity. |
| [1_did_issues_nft](./1_advanced/1_did_issues_nft.rs) | Demonstrates how an identity can issue and own NFTs, and how observers can verify the issuer of the NFT. |
| [2_nft_owns_did](./1_advanced/2_nft_owns_did.rs) | Demonstrates how an identity can be owned by NFTs, and how observers can verify that relationship. |
| [3_did_issues_tokens](./1_advanced/3_did_issues_tokens.rs) | Demonstrates how an identity can issue and control a Token Foundry and its tokens. |
| [4_alias_output_history](./1_advanced/4_alias_output_history.rs) | Demonstrates fetching the history of an Alias Output. |
| [4_identity_history](./1_advanced/4_identity_history.rs) | Demonstrates fetching the history of an identity. |
| [5_custom_resolution](./1_advanced/5_custom_resolution.rs) | Demonstrates how to set up a resolver using custom handlers. |
| [6_domain_linkage](./1_advanced/6_domain_linkage) | Demonstrates how to link a domain and a DID and verify the linkage. |
| [7_sd_jwt](./1_advanced/7_sd_jwt) | Demonstrates how to create and verify selective disclosure verifiable credentials. |
| [8_status_list_2021](./1_advanced/8_status_list_2021.rs) | Demonstrates how to revoke a credential using `StatusList2021`. |
| [9_zkp](./1_advanced/9_zkp.rs) | Demonstrates how to create an Anonymous Credential with BBS+. |
| [10_zkp_revocation](./1_advanced/10_zkp_revocation.rs) | Demonstrates how to revoke a credential. |
| [11_linked_verifiable_presentation](./1_advanced/11_linked_verifiable_presentation.rs) | Demonstrates how to link a public Verifiable Presentation to an identity and how it can be verified. |
1 change: 0 additions & 1 deletion examples/utils/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ where
S: Signer<IotaKeySignature> + Sync,
{
// Create a new DID document with a placeholder DID.
// The DID will be derived from the Alias Id of the Alias Output after publishing.
let mut unpublished: IotaDocument = IotaDocument::new(identity_client.network());
let verification_method_fragment = unpublished
.generate_method(
Expand Down
Loading

0 comments on commit 40cb627

Please sign in to comment.