import { Wallet } from "ethers";
import { Sdk } from "@peaq-network/sdk";
// Reuse the ECDSAKeyring class from previous page
class ECDSAKeyring {
constructor(privateKey) {
if (privateKey) {
this.wallet = new Wallet(privateKey);
} else {
this.wallet = Wallet.createRandom(); // generates new key
}
}
getAddress() {
return this.wallet.address;
}
getPrivateKey() {
return this.wallet.privateKey;
}
async signMessage(message) {
return this.wallet.signMessage(message);
}
}
// Simulate machine-generated data and store it in peaq storage
async function storeMachineData(key, machineWallet){
const HTTPS_BASE_URL = "https://peaq-agung.api.onfinality.io/public"; // agung testnet
const sdk = await Sdk.createInstance({
baseUrl: HTTPS_BASE_URL,
chainType: Sdk.ChainType.EVM
});
const message = "mock data to be stored"; // Replace with dynamic data if needed
const tx = await sdk.storage.addItem({
itemType: key,
item: message
});
const receipt = await Sdk.sendEvmTx({
tx: tx,
baseUrl: HTTPS_BASE_URL,
seed: machineWallet.getPrivateKey()
});
console.log(`Stored message for ${key}: "${message}"`)
return message;
}
async function signMachineData(message, machineWallet){
return await machineWallet.signMessage(message);
}
// Store machine data approval in peaq storage using the admin wallet
async function storeAdminApproval(adminWallet, machineWallet, key, machineSignature) {
const HTTPS_BASE_URL = "https://peaq-agung.api.onfinality.io/public"; // agung testnet
// Prepare the content to be approved. Be wary about the 256 byte limit.
const storageContent = {
storageKey: key,
machineSignature: machineSignature
};
const sdk = await Sdk.createInstance({
baseUrl: HTTPS_BASE_URL,
chainType: Sdk.ChainType.EVM
});
// We reuse the same key to link the machine data with the admin approval.
const tx = await sdk.storage.addItem({
itemType: key,
item: storageContent
});
// The admin sends the transaction to store the approval.
const receipt = await Sdk.sendEvmTx({
tx: tx,
baseUrl: HTTPS_BASE_URL,
seed: adminWallet.getPrivateKey()
});
console.log(`Admin stored approval for ${key}`);
// Return the content that will be signed by the admin.
return storageContent;
}
// The admin signs the canonical representation of the stored data.
async function adminSignData(adminWallet, unsignedContent) {
const canonicalContent = JSON.stringify(unsignedContent);
return await adminWallet.signMessage(canonicalContent);
}
async function updateDID(machineWallet, adminWallet, key, adminSignature){
const HTTPS_BASE_URL = "https://peaq-agung.api.onfinality.io/public";
const WSS_BASE_URL = "wss://wss-async.agung.peaq.network"; // Used to read previously stored DID
const sdk = await Sdk.createInstance({
baseUrl: HTTPS_BASE_URL,
chainType: Sdk.ChainType.EVM
});
const name = "project_name"; // Same name as before
const customFields = {
verifications: [{
type: "EcdsaSecp256k1RecoveryMethod2020"
}],
signature: {
type: "EcdsaSecp256k1RecoveryMethod2020",
issuer: adminWallet.getAddress(),
hash: adminSignature
},
services: [
{
id: '#unsignedMessage',
type: 'peaqStorage',
data: key // Reference to the stored unsigned admin & machine data in peaq storage
},
{
id: '#admin',
type: 'admin',
data: adminWallet.getAddress()
},
]
};
// Create a transaction object to update the DID
const tx = await sdk.did.update({
name: name,
address: machineWallet.getAddress(),
wssBaseUrl: WSS_BASE_URL,
customDocumentFields: customFields
});
// Submit the transaction to the network using the machine’s private key
const receipt = await Sdk.sendEvmTx({
tx: tx,
baseUrl: HTTPS_BASE_URL,
seed: machineWallet.getPrivateKey()
});
console.log(`Successfully Updated DID Document`);
}
async function main(){
// 1. Initialize Wallets
const machineWallet = new ECDSAKeyring(MACHINE_PRIVATE);
const adminWallet = new ECDSAKeyring(ADMIN_PRIVATE);
// 2. Generate & Store Machine Data
const key = crypto.randomUUID();
const message = await storeMachineData(key, machineWallet);
// 3. Sign Machine Data
const machineSignature = await signMachineData(message, machineWallet);
// 4. Admin Approval
const unsignedContent = await storeAdminApproval(adminWallet, machineWallet, key, machineSignature);
const adminSignature = await adminSignData(adminWallet, unsignedContent);
// 5. Update DID Document
await updateDID(machineWallet, adminWallet, key, adminSignature);
}
main();