-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
147 lines (124 loc) · 4.6 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2020-2023 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
import {
IotaDocument,
IotaIdentityClient,
JwkMemStore,
JwsAlgorithm,
KeyIdMemStore,
MethodScope,
Storage,
} from "@iota/identity-wasm/node";
import { AliasOutput, Client, MnemonicSecretManager, Utils, IOutputsResponse, SecretManager } from "@iota/sdk-wasm/node";
export const API_ENDPOINT = "https://api.testnet.shimmer.network";
export const FAUCET_ENDPOINT = "https://faucet.testnet.shimmer.network/api/enqueue";
/** Demonstrates how to update a DID document in an existing Alias Output. */
export async function create_identity() {
const client = new Client({
primaryNode: API_ENDPOINT,
localPow: true,
});
const didClient = new IotaIdentityClient(client);
// Get the Bech32 human-readable part (HRP) of the network.
const networkHrp: string = await didClient.getNetworkHrp();
const mnemonicSecretManager: MnemonicSecretManager = {
mnemonic: Utils.generateMnemonic(),
};
// Generate a random mnemonic for our wallet.
const secretManager: SecretManager = new SecretManager(mnemonicSecretManager);
const walletAddressBech32 = (await secretManager.generateEd25519Addresses({
accountIndex: 0,
range: {
start: 0,
end: 1,
},
bech32Hrp: networkHrp,
}))[0];
console.log("Wallet address Bech32:", walletAddressBech32);
// Request funds for the wallet, if needed - only works on development networks.
await ensureAddressHasFunds(client, walletAddressBech32);
// Create a new DID document with a placeholder DID.
// The DID will be derived from the Alias Id of the Alias Output after publishing.
const document = new IotaDocument(networkHrp);
const storage: Storage = new Storage(new JwkMemStore(), new KeyIdMemStore());
// Insert a new Ed25519 verification method in the DID document.
await document.generateMethod(
storage,
JwkMemStore.ed25519KeyType(),
JwsAlgorithm.EdDSA,
"#key-1",
MethodScope.VerificationMethod(),
);
// Construct an Alias Output containing the DID document, with the wallet address
// set as both the state controller and governor.
const address = Utils.parseBech32Address(walletAddressBech32);
const aliasOutput: AliasOutput = await didClient.newDidOutput(address, document);
console.log("Alias Output:", JSON.stringify(aliasOutput, null, 2));
// Publish the Alias Output and get the published DID document.
const published = await didClient.publishDidOutput(mnemonicSecretManager, aliasOutput);
console.log("Published DID document:", JSON.stringify(published, null, 2));
}
/** Request funds from the faucet API, if needed, and wait for them to show in the wallet. */
export async function ensureAddressHasFunds(client: Client, addressBech32: string) {
let balance = await getAddressBalance(client, addressBech32);
if (balance > BigInt(0)) {
return;
}
await requestFundsFromFaucet(addressBech32);
for (let i = 0; i < 9; i++) {
// Wait for the funds to reflect.
await new Promise(f => setTimeout(f, 5000));
let balance = await getAddressBalance(client, addressBech32);
if (balance > BigInt(0)) {
break;
}
}
}
/** Returns the balance of the given Bech32-encoded address. */
async function getAddressBalance(client: Client, addressBech32: string): Promise<bigint> {
const outputIds: IOutputsResponse = await client.basicOutputIds([
{ address: addressBech32 },
{ hasExpiration: false },
{ hasTimelock: false },
{ hasStorageDepositReturn: false },
]);
const outputs = await client.getOutputs(outputIds.items);
let totalAmount = BigInt(0);
for (const output of outputs) {
totalAmount += output.output.getAmount();
}
return totalAmount;
}
/** Request tokens from the faucet API. */
async function requestFundsFromFaucet(addressBech32: string) {
const requestObj = JSON.stringify({ address: addressBech32 });
let errorMessage, data;
try {
const response = await fetch(FAUCET_ENDPOINT, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: requestObj,
});
if (response.status === 202) {
errorMessage = "OK";
} else if (response.status === 429) {
errorMessage = "too many requests, please try again later.";
} else {
data = await response.json();
// @ts-ignore
errorMessage = data.error.message;
}
} catch (error) {
errorMessage = error;
}
if (errorMessage != "OK") {
throw new Error(`failed to get funds from faucet: ${errorMessage}`);
}
}
create_identity()
.catch((error) => {
console.log("Example error:", error);
});