Разработка системы academic credentials на блокчейне
Academic credentials — это не только диплом. Это микросертификаты, badge-и, подтверждения участия в конференциях, специализации, профессиональные лицензии. Система должна поддерживать весь этот спектр и быть совместима с международными стандартами — прежде всего W3C Verifiable Credentials и IMS Open Badges 3.0.
ERC-1155 для credential портфолио
В отличие от диплома (один документ), credential портфолио — коллекция badge-ей разных типов. ERC-1155 multi-token стандарт подходит лучше чем ERC-721: один контракт обслуживает все типы credentials, batch transfer для выдачи нескольких badge-ей одновременно.
contract AcademicCredentials is ERC1155, AccessControl {
bytes32 public constant ISSUER_ROLE = keccak256("ISSUER_ROLE");
struct CredentialType {
string name;
string description;
string category; // "DEGREE", "CERTIFICATE", "BADGE", "MICROCREDENTIAL"
uint256 totalIssued;
bool active;
}
// tokenId => CredentialType
mapping(uint256 => CredentialType) public credentialTypes;
// tokenId => recipient => metadata (исключает дупликаты)
mapping(uint256 => mapping(address => bytes32)) public credentialMetadata;
// SBT: запрет передачи credentials
function safeTransferFrom(address, address, uint256, uint256, bytes memory)
public pure override
{
revert("Credentials are non-transferable");
}
function safeBatchTransferFrom(address, address, uint256[] memory, uint256[] memory, bytes memory)
public pure override
{
revert("Credentials are non-transferable");
}
function issueCredential(
address recipient,
uint256 credentialTypeId,
bytes32 metadataHash
) external onlyRole(ISSUER_ROLE) {
require(credentialTypes[credentialTypeId].active, "Credential type inactive");
require(credentialMetadata[credentialTypeId][recipient] == 0, "Already issued");
_mint(recipient, credentialTypeId, 1, "");
credentialMetadata[credentialTypeId][recipient] = metadataHash;
credentialTypes[credentialTypeId].totalIssued++;
emit CredentialIssued(recipient, credentialTypeId, metadataHash);
}
// Batch выдача нескольких типов credentials одному получателю
function batchIssueCredentials(
address recipient,
uint256[] calldata credentialTypeIds,
bytes32[] calldata metadataHashes
) external onlyRole(ISSUER_ROLE) {
uint256[] memory amounts = new uint256[](credentialTypeIds.length);
for (uint i = 0; i < credentialTypeIds.length; i++) {
amounts[i] = 1;
}
_mintBatch(recipient, credentialTypeIds, amounts, "");
}
}
Metadata стандарт
IPFS metadata для каждого credential по Open Badges 3.0 схеме:
{
"@context": ["https://www.w3.org/2018/credentials/v1", "https://w3id.org/openbadges/v3"],
"type": ["VerifiableCredential", "OpenBadgeCredential"],
"name": "Advanced Solidity Developer",
"description": "Completion of Advanced Solidity course with score ≥ 85%",
"image": "ipfs://QmBadgeImage...",
"criteria": {
"narrative": "Complete all modules, pass final exam with score ≥ 85%"
},
"credentialSubject": {
"achievement": {
"achievementType": "Certificate",
"creator": { "id": "did:ethr:0xIssuerAddress", "name": "Blockchain Academy" },
"name": "Advanced Solidity Developer"
}
},
"issuanceDate": "2024-01-15T10:00:00Z"
}
Верификация работодателем
Упрощённый flow для HR:
async function verifyCredentialPortfolio(
candidateAddress: string,
requiredCredentials: string[]
): Promise<PortfolioVerification> {
const tokenIds = await Promise.all(
requiredCredentials.map(name => getTokenIdByName(name))
);
const balances = await credentialsContract.balanceOfBatch(
tokenIds.map(() => candidateAddress),
tokenIds
);
const verifiedCredentials = await Promise.all(
tokenIds.map(async (tokenId, index) => {
if (balances[index].eq(0)) return { name: requiredCredentials[index], valid: false };
const metadataHash = await credentialsContract.credentialMetadata(tokenId, candidateAddress);
const metadata = await fetchFromIPFS(metadataHash);
return {
name: requiredCredentials[index],
valid: true,
issuedAt: metadata.issuanceDate,
issuer: metadata.credentialSubject?.achievement?.creator?.name,
};
})
);
return {
candidateAddress,
verifiedCredentials,
allRequirementsMet: verifiedCredentials.every(c => c.valid),
};
}
Система academic credentials с ERC-1155, Open Badges 3.0 metadata и HR верификационным порталом — 4-6 недель разработки. Добавление W3C VC подписей и DID интеграции — ещё 2-3 недели.







