import { CulturaSDK, ParentDigitalAsset } from "@cultura/sdk";
import { parseEther, getAddress } from "viem"; // Example utility
/**
* Simulates licensing a parent asset using the Mock Protocol.
* Assumes sdk is initialized for the LICENSEE.
*/
async function simulateLicenseAcquisition(
sdk: CulturaSDK,
parentCollection: `0x${string}`,
parentTokenId: bigint
) {
try {
console.log(
`Simulating license acquisition for ${parentCollection}#${parentTokenId}...`
);
// Ensure the mock protocol client is available
if (!sdk.mockLicensingProtocol) {
throw new Error(
"Mock Licensing Protocol client not available in SDK config."
);
}
const txHash = await sdk.mockLicensingProtocol.licenseDigitalAsset(
parentCollection,
parentTokenId
);
await sdk.publicClient.waitForTransactionReceipt({ hash: txHash });
console.log("Mock license acquired, Tx:", txHash);
} catch (error) {
console.error("Error simulating license acquisition:", error);
throw error;
}
}
/**
* Creates and attests a Licensed Creative Asset using the Mock Protocol's
* convenience function.
* Assumes sdk is initialized for the LICENSEE.
*/
async function createAndAttestLicensedAsset(
sdk: CulturaSDK,
licenseeAddress: `0x${string}`,
parentRights: readonly ParentDigitalAsset[], // Info about the licensed parent(s) including royaltySplit
newAssetName: string,
newAssetDescription: string,
newAssetImageUrl?: string
) {
try {
// Ensure necessary SDK clients are available
if (
!sdk.attestationService ||
!sdk.schemaRegistry ||
!sdk.bondToken ||
!sdk.mockLicensingProtocol ||
!sdk.culturaDigitalAsset
) {
throw new Error(
"Required SDK clients (Attestation, Schema, BondToken, MockLicensing, DigitalAsset) not configured."
);
}
// --- Prepare for Delegated Attestation ---
console.log("Preparing signature for delegated attestation...");
const signatureParams =
await sdk.attestationService.signForDelegatedAttestation(licenseeAddress);
console.log("Signature obtained.");
// --- Define Attestation Parameters ---
const schemaStr =
"string digitalAssetName, string digitalAssetDescription, uint256 grade"; // Example schema
const schemaUID = await sdk.schemaRegistry.getOrRegisterSchema(
schemaStr,
true // Assuming revocable
);
const grade = 3n; // Example: Grade C for the new attestation
const bondAmount = parseEther("0.0001"); // Example bond for Grade C attestation fee
// --- Approve Bond Tokens (Licensee needs to approve CAS for the attestation bond) ---
const casAddress = sdk.config.contracts?.attestationService;
if (!casAddress) throw new Error("CAS address not configured");
console.log(`Approving ${bondAmount} tokens for CAS...`);
const approveTx = await sdk.bondToken.approve(casAddress, bondAmount);
await sdk.publicClient.waitForTransactionReceipt({ hash: approveTx });
console.log("Bond token approved for attestation.");
// --- Call Mock Protocol's createLicensedAsset ---
console.log("Calling createLicensedAsset on Mock Protocol...");
// This function bundles minting and attestation
const result = await sdk.mockLicensingProtocol.createLicensedAsset(
{
name: newAssetName,
description: newAssetDescription,
imageUrl: newAssetImageUrl,
},
signatureParams,
schemaUID,
bondAmount, // Pass the bond amount required for the attestation
grade,
parentRights
// externalNFT parameter can be added here if licensing an external asset
);
console.log("createLicensedAsset call successful.");
console.log(` New Licensed Asset ID: ${result.licensedAssetId}`);
console.log(` Attestation UID: ${result.attestationInfo.attestationUid}`);
console.log(
` Rights Bound Account: ${result.attestationInfo.rightsBoundAccount}`
);
console.log(` Transaction State: ${result.transactionState}`); // Should be 'complete'
if (result.transactionState !== "complete") {
throw new Error("createLicensedAsset did not complete successfully.");
}
return result;
} catch (error) {
console.error("Error creating licensed asset:", error);
throw error;
}
}
/**
* Optional: Simulate verification of the newly created Licensed Creative Asset's attestation.
* Assumes sdk is initialized for a VERIFIER.
*/
async function simulateVerificationOfLicensedAsset(
sdk: CulturaSDK, // SDK instance for the VERIFIER
attestationUID: `0x${string}`,
verificationBond: bigint // e.g., parseEther("0.01")
) {
try {
// Ensure necessary SDK clients are available
if (
!sdk.bondToken ||
!sdk.mockLicensingProtocol ||
!sdk.attestationService
) {
throw new Error(
"Required SDK clients (BondToken, MockLicensing, Attestation) not configured."
);
}
// --- Approve Bond Tokens (Verifier needs to approve CAS) ---
// The mock protocol's verifyLicensedAsset calls CAS.verifyAttestation internally.
const casAddress = sdk.config.contracts?.attestationService;
if (!casAddress) throw new Error("CAS address not configured");
console.log(
`Approving ${verificationBond} tokens for verification via CAS...`
);
const approveTx = await sdk.bondToken.approve(casAddress, verificationBond);
await sdk.publicClient.waitForTransactionReceipt({ hash: approveTx });
console.log("Bond token approved for verification.");
// --- Call Mock Protocol's verifyLicensedAsset ---
console.log(
`Calling verifyLicensedAsset for attestation ${attestationUID}...`
);
// This simulates the licensing protocol verifying the attestation
const verifyTxHash = await sdk.mockLicensingProtocol.verifyLicensedAsset(
attestationUID,
verificationBond
);
await sdk.publicClient.waitForTransactionReceipt({ hash: verifyTxHash });
console.log("Verification simulation complete, Tx:", verifyTxHash);
// You could potentially query the asset's level again here to see if it reached Level 2
// const attestationData = await sdk.attestationService.getAttestation(attestationUID);
// const level = await sdk.attestationService.getDigitalAssetLevel(attestationData.digitalAssetAddress, attestationData.digitalAssetId);
// console.log("Asset level after mock verification:", level);
} catch (error) {
console.error("Error verifying licensed asset:", error);
throw error;
}
}
// --- Example Usage Flow ---
// async function runFullLicensingFlow() {
// // Assume licenseeSdk is initialized and connected
// const licenseeSdk = CulturaSDK.createWithWallet(window.ethereum, { chain: 'testnet' });
// if (!licenseeSdk.walletClient?.account) {
// console.error("Licensee wallet not connected");
// return;
// }
// const licenseeAddress = licenseeSdk.walletClient.account.address;
// // Define Parent Asset Info
// const parentCollection = getAddress('0xParentContractAddress...'); // Use getAddress for checksum
// const parentTokenId = 1n;
// const parentOwner = getAddress('0xParentOwnerAddress...'); // Use getAddress
// try {
// // 1. Verify Parent Asset is Level 2 (Example Check)
// const parentLevel = await licenseeSdk.attestationService.getDigitalAssetLevel(parentCollection, parentTokenId);
// if (parentLevel !== 2) {
// console.error(`Parent asset ${parentTokenId} is not Level 2.`);
// return;
// }
// console.log("Parent asset confirmed Level 2.");
// // 2. Simulate getting the license via Mock Protocol
// await simulateLicenseAcquisition(licenseeSdk, parentCollection, parentTokenId);
// // 3. Define parent info for the new asset, including royalty split
// const parentRightsInfo: readonly ParentDigitalAsset[] = [{
// parentCollection: parentCollection,
// parentDigitalAssetId: parentTokenId,
// owner: parentOwner,
// royaltySplit: 5000n // 50% royalty split example (5000 basis points)
// }];
// // 4. Create and attest the new licensed asset using the mock protocol's convenience function
// const { licensedAssetId, attestationInfo } = await createAndAttestLicensedAsset(
// licenseeSdk,
// licenseeAddress,
// parentRightsInfo,
// "My Licensed Derivative",
// "Based on Parent Asset #1",
// "ipfs://..." // Optional image URL for the new asset
// );
// console.log(`New asset ${licensedAssetId} created and attested (Level 1). Attestation: ${attestationInfo.attestationUid}`);
// // 5. Optional: Have a verifier verify the new asset's attestation using the mock protocol
// // Assume verifierSdk is initialized for a different account
// // const verifierSdk = CulturaSDK.createWithWallet(...);
// // await simulateVerificationOfLicensedAsset(verifierSdk, attestationInfo.attestationUid, parseEther("0.02"));
// // console.log(`Attestation ${attestationInfo.attestationUid} submitted for verification.`);
// } catch (e) {
// console.error("Full licensing flow failed:", e);
// }
// }
// runFullLicensingFlow();