Moonbeam上的Identity Precompile¶
概览¶
Identity Precompile是一个Solidity接口,用于创建、管理和检索链上身份信息。身份与账户相关联,并包括个人信息,例如法定姓名、对外显示的名称、网站、Twitter名称、Riot(现为Element)名称等。您也可以通过填写自定义字段包含任何其他相关信息。
Identity Precompile直接与Substrate的Identity Pallet交互,以提供创建和管理身份所需的功能。此Pallet以Rust编写,通常无法从Moonbeam的以太坊侧直接访问。然而,Identity Precompile允许您直接从Solidity接口访问此功能。
Identity Precompile位于以下地址:
0x0000000000000000000000000000000000000818
0x0000000000000000000000000000000000000818
0x0000000000000000000000000000000000000818
Identity Precompile Solidity接口¶
Identity.sol
是一个Solidity接口,允许开发者与预编译函数进行交互:
Identity.sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.8.3;
/// @dev The Identity contract's address.
address constant IDENTITY_ADDRESS = 0x0000000000000000000000000000000000000818;
/// @dev The Identity contract's instance.
Identity constant IDENTITY_CONTRACT = Identity(IDENTITY_ADDRESS);
/// @author The Moonbeam Team
/// @title Pallet Identity Interface
/// @title The interface through which solidity contracts will interact with the Identity pallet
/// @custom:address 0x0000000000000000000000000000000000000818
interface Identity {
/// @dev Associated raw data.
struct Data {
/// Is `true` if it represents data, else the absense of data is represented by `false`.
bool hasData;
/// The contained value.
bytes value;
}
/// @dev The super-identity of an alternative "sub" identity.
struct SuperOf {
/// Is `true` if the struct is valid, `false` otherwise.
bool isValid;
/// The super account.
address account;
/// The associated data.
Data data;
}
/// @dev Alternative "sub" identities of an account.
struct SubsOf {
/// The deposit against this identity.
uint256 deposit;
/// The sub accounts
address[] accounts;
}
/// @dev Registrar judgements are limited to attestations on these fields.
struct IdentityFields {
/// Set to `true` if the display field is supported, `false` otherwise.
bool display;
/// Set to `true` if the legal field is supported, `false` otherwise.
bool legal;
/// Set to `true` if the web field is supported, `false` otherwise.
bool web;
/// Set to `true` if the riot field is supported, `false` otherwise.
bool riot;
/// Set to `true` if the email field is supported, `false` otherwise.
bool email;
/// Set to `true` if the PGP Fingerprint field is supported, `false` otherwise.
bool pgpFingerprint;
/// Set to `true` if the image field is supported, `false` otherwise.
bool image;
/// Set to `true` if the twitter field is supported, `false` otherwise.
bool twitter;
}
/// @dev Registrar info.
struct Registrar {
/// Is `true` if the struct is valid, `false` otherwise.
bool isValid;
/// The registrar's index.
uint32 index;
/// The account address.
address account;
/// Amount required to be given to the registrar for them to provide judgement.
uint256 fee;
/// Relevant fields for this registrar.
IdentityFields fields;
}
/// @dev Represents an additional field in identity info.
struct Additional {
/// The assciated key.
Data key;
/// The assciated value.
Data value;
}
/// @dev The identity information set for an account.
struct IdentityInfo {
/// Represents the additional fields for the identity.
Additional[] additional;
/// Represents the display info for the identity.
Data display;
/// Represents the legal info for the identity.
Data legal;
/// Represents the web info for the identity.
Data web;
/// Represents the riot info for the identity.
Data riot;
/// Represents the email info for the identity.
Data email;
/// Set to `true` if `pgpFingerprint` is set, `false` otherwise.
bool hasPgpFingerprint;
/// Represents a 20-byte the PGP fingerprint info for the identity.
bytes pgpFingerprint;
/// Represents the image info for the identity.
Data image;
/// Represents the twitter info for the identity.
Data twitter;
}
/// @dev Judgement provided by a registrar.
struct Judgement {
/// The default value; no opinion is held.
bool isUnknown;
/// No judgement is yet in place, but a deposit is reserved as payment for providing one.
bool isFeePaid;
/// The deposit reserved for providing a judgement.
uint256 feePaidDeposit;
/// The data appears to be reasonably acceptable in terms of its accuracy.
bool isReasonable;
/// The target is known directly by the registrar and the registrar can fully attest to it.
bool isKnownGood;
/// The data was once good but is currently out of date.
bool isOutOfDate;
/// The data is imprecise or of sufficiently low-quality to be problematic.
bool isLowQuality;
/// The data is erroneous. This may be indicative of malicious intent.
bool isErroneous;
}
/// @dev Judgement item provided by a registrar.
struct JudgementInfo {
/// The registrar's index that provided this judgement.
uint32 registrarIndex;
/// The registrar's provided judgement.
Judgement judgement;
}
/// @dev Registrar info.
struct Registration {
/// Is `true` if the struct is valid, `false` otherwise.
bool isValid;
/// The judgments provided on this identity.
JudgementInfo[] judgements;
/// Amount required to be given to the registrar for them to provide judgement.
uint256 deposit;
/// The associated identity info.
IdentityInfo info;
}
/// @dev Alternative "sub" identity of an account.
struct SubAccount {
/// The account address.
address account;
/// The associated data.
Data data;
}
/// @dev Retrieve identity information for an account.
/// @custom:selector f0eb5e54
/// @param who The requested account
function identity(address who) external view returns (Registration memory);
/// @dev Retrieve super account for an account.
/// @custom:selector c18110d6
/// @param who The requested account
function superOf(address who) external view returns (SuperOf memory);
/// @dev Retrieve sub accounts for an account.
/// @custom:selector 3f08986b
/// @param who The requested account
function subsOf(address who) external view returns (SubsOf memory);
/// @dev Retrieve the registrars.
/// @custom:selector e88e512e
function registrars() external view returns (Registrar[] memory);
/// @dev Set identity info for the caller.
/// @custom:selector 7e08b4cb
/// @param info The identity info
function setIdentity(IdentityInfo memory info) external;
/// @dev Set sub accounts for the caller.
/// @custom:selector 5a5a3591
/// @param subs The sub accounts
function setSubs(SubAccount[] memory subs) external;
/// @dev Clears identity of the caller.
/// @custom:selector 7a6a10c7
function clearIdentity() external;
/// @dev Requests registrar judgement on caller's identity.
/// @custom:selector d523ceb9
/// @param regIndex The registrar's index
/// @param maxFee The maximum fee the caller is willing to pay
function requestJudgement(uint32 regIndex, uint256 maxFee) external;
/// @dev Cancels the caller's request for judgement from a registrar.
/// @custom:selector c79934a5
/// @param regIndex The registrar's index
function cancelRequest(uint32 regIndex) external;
/// @dev Sets the registrar's fee for providing a judgement. Caller must be the account at the index.
/// @custom:selector a541b37d
/// @param regIndex The registrar's index
/// @param fee The fee the registrar will charge
function setFee(uint32 regIndex, uint256 fee) external;
/// @dev Sets the registrar's account. Caller must be the account at the index.
/// @custom:selector 889bc198
/// @param regIndex The registrar's index
/// @param newAccount The new account to set
function setAccountId(uint32 regIndex, address newAccount) external;
/// @dev Sets the registrar's identity fields. Caller must be the account at the index.
/// @custom:selector 05297450
/// @param regIndex The registrar's index
/// @param fields The identity fields
function setFields(uint32 regIndex, IdentityFields memory fields) external;
/// @dev Provides judgement on an accounts identity.
/// @custom:selector cd7663a4
/// @param regIndex The registrar's index
/// @param target The target account to provide judgment for
/// @param judgement The judgement to provide
/// @param identity The hash of the identity info
function provideJudgement(
uint32 regIndex,
address target,
Judgement memory judgement,
bytes32 identity
) external;
/// @dev Add a "sub" identity account for the caller.
/// @custom:selector 98717196
/// @param sub The sub account
/// @param data The associated data
function addSub(address sub, Data memory data) external;
/// @dev Rename a "sub" identity account of the caller.
/// @custom:selector 452df561
/// @param sub The sub account
/// @param data The new assocaited data
function renameSub(address sub, Data memory data) external;
/// @dev Removes a "sub" identity account of the caller.
/// @custom:selector b0a323e0
/// @param sub The sub account
function removeSub(address sub) external;
/// @dev Removes the sender as a sub-account.
/// @custom:selector d5a3c2c4
function quitSub() external;
/// @dev An identity was set or reset (which will remove all judgements).
/// @custom:selector 3839f7832b2a6263aa1fd5040f37d10fd4f9e9c4a9ef07ec384cb1cef9fb4c0e
/// @param who Address of the target account
event IdentitySet(address who);
/// @dev An identity was cleared, and the given balance returned.
/// @custom:selector 3839f7832b2a6263aa1fd5040f37d10fd4f9e9c4a9ef07ec384cb1cef9fb4c0e
/// @param who Address of the target account
event IdentityCleared(address who);
/// @dev A judgement was asked from a registrar.
/// @custom:selector 3839f7832b2a6263aa1fd5040f37d10fd4f9e9c4a9ef07ec384cb1cef9fb4c0e
/// @param who Address of the requesting account
/// @param registrarIndex The registrar's index
event JudgementRequested(address who, uint32 registrarIndex);
/// @dev A judgement request was retracted.
/// @custom:selector 3839f7832b2a6263aa1fd5040f37d10fd4f9e9c4a9ef07ec384cb1cef9fb4c0e
/// @param who Address of the target account.
/// @param registrarIndex The registrar's index
event JudgementUnrequested(address who, uint32 registrarIndex);
/// @dev A judgement was given by a registrar.
/// @custom:selector 3839f7832b2a6263aa1fd5040f37d10fd4f9e9c4a9ef07ec384cb1cef9fb4c0e
/// @param target Address of the target account
/// @param registrarIndex The registrar's index
event JudgementGiven(address target, uint32 registrarIndex);
/// @dev A sub-identity was added to an identity and the deposit paid.
/// @custom:selector 3839f7832b2a6263aa1fd5040f37d10fd4f9e9c4a9ef07ec384cb1cef9fb4c0e
/// @param sub Address of the sub account
/// @param main Address of the main account
event SubIdentityAdded(address sub, address main);
/// @dev A sub-identity was removed from an identity and the deposit freed.
/// @custom:selector 3839f7832b2a6263aa1fd5040f37d10fd4f9e9c4a9ef07ec384cb1cef9fb4c0e
/// @param sub Address of the sub account
/// @param main Address of the main account
event SubIdentityRemoved(address sub, address main);
/// @dev A sub-identity was cleared and the given deposit repatriated from the main identity account to the sub-identity account
/// @custom:selector 3839f7832b2a6263aa1fd5040f37d10fd4f9e9c4a9ef07ec384cb1cef9fb4c0e
/// @param sub Address of the sub account
event SubIdentityRevoked(address sub);
}
Identity Precompile包含一些任何人都可以调用的函数,以及只能由注册人调用的一些与判断相关的函数。任何人都可以调用的函数包含:
- identity(address who) - 返回给定账户的注册信息
- superOf(address who) - 检索子账户的超级账户。如果给定账户不是子账户,则返回的地址为
0x0000000000000000000000000000000000000000
- subsOf(address who) - 返回给定账户的子账户。如果给定账户没有任何子账户,则返回(
[]
) - registrars() - 返回注册人列表
- setIdentity(IdentityInfo memory info) - 为调用者设置身份
- setSubs(SubAccount[] memory subs) - 为调用者设置子账户
- clearIdentity() - 为调用者清除身份
- requestJudgement(uint32 regIndex, uint256 maxFee) - 请求指定注册人的判断以及调用者愿意支付的最高费用
- cancelRequest(uint32 regIndex) - 取消调用者对给定注册人的判断请求
- addSub(address sub, Data memory data) - 为调用者添加子身份账户
- renameSub(address sub, Data memory data) - 为调用者重命名子身份账户
- removeSub(address sub) - 为调用者移除子身份账户
- quitSub(address sub) - 将调用者从子身份账户移除
判断相关的函数必须由注册人调用,并且调用者必须是对应regIndex
的注册人账户:
- setFee(uint32 regIndex, uint256 fee) - 为注册人设置费用
- setAccountId(uint32 regIndex, address newAccount) - 为注册人设置新账户
- setFields(uint32 regIndex, IdentityFields memory fields) - 设置注册人的身份
- provideJudgement(uint32 regIndex, address target, Judgement memory judgement, bytes32 identity) - 提供对账户身份的判断
与Solidity接口交互¶
以下部分将介绍如何使用以太坊库(例如 Ethers.js、Web3.js和Web3.py)与Identity Precompile交互。
The examples in this guide will be on Moonbase Alpha. 本教程中的示例将在Moonbase Alpha上操作。
使用以太坊库¶
要使用以太坊库与Identity Precompile的Solidity接口交互,将您将需要用到Identity Precompile的ABI。
Identity Precompile ABI
[
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "who",
"type": "address"
}
],
"name": "IdentityCleared",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "who",
"type": "address"
}
],
"name": "IdentitySet",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "target",
"type": "address"
},
{
"indexed": false,
"internalType": "uint32",
"name": "registrarIndex",
"type": "uint32"
}
],
"name": "JudgementGiven",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "who",
"type": "address"
},
{
"indexed": false,
"internalType": "uint32",
"name": "registrarIndex",
"type": "uint32"
}
],
"name": "JudgementRequested",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "who",
"type": "address"
},
{
"indexed": false,
"internalType": "uint32",
"name": "registrarIndex",
"type": "uint32"
}
],
"name": "JudgementUnrequested",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "sub",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "main",
"type": "address"
}
],
"name": "SubIdentityAdded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "sub",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "main",
"type": "address"
}
],
"name": "SubIdentityRemoved",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "sub",
"type": "address"
}
],
"name": "SubIdentityRevoked",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "sub",
"type": "address"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "data",
"type": "tuple"
}
],
"name": "addSub",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "regIndex",
"type": "uint32"
}
],
"name": "cancelRequest",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "clearIdentity",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "who",
"type": "address"
}
],
"name": "identity",
"outputs": [
{
"components": [
{
"internalType": "bool",
"name": "isValid",
"type": "bool"
},
{
"components": [
{
"internalType": "uint32",
"name": "registrarIndex",
"type": "uint32"
},
{
"components": [
{
"internalType": "bool",
"name": "isUnknown",
"type": "bool"
},
{
"internalType": "bool",
"name": "isFeePaid",
"type": "bool"
},
{
"internalType": "uint256",
"name": "feePaidDeposit",
"type": "uint256"
},
{
"internalType": "bool",
"name": "isReasonable",
"type": "bool"
},
{
"internalType": "bool",
"name": "isKnownGood",
"type": "bool"
},
{
"internalType": "bool",
"name": "isOutOfDate",
"type": "bool"
},
{
"internalType": "bool",
"name": "isLowQuality",
"type": "bool"
},
{
"internalType": "bool",
"name": "isErroneous",
"type": "bool"
}
],
"internalType": "struct Identity.Judgement",
"name": "judgement",
"type": "tuple"
}
],
"internalType": "struct Identity.JudgementInfo[]",
"name": "judgements",
"type": "tuple[]"
},
{
"internalType": "uint256",
"name": "deposit",
"type": "uint256"
},
{
"components": [
{
"components": [
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "key",
"type": "tuple"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "value",
"type": "tuple"
}
],
"internalType": "struct Identity.Additional[]",
"name": "additional",
"type": "tuple[]"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "display",
"type": "tuple"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "legal",
"type": "tuple"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "web",
"type": "tuple"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "riot",
"type": "tuple"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "email",
"type": "tuple"
},
{
"internalType": "bool",
"name": "hasPgpFingerprint",
"type": "bool"
},
{
"internalType": "bytes",
"name": "pgpFingerprint",
"type": "bytes"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "image",
"type": "tuple"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "twitter",
"type": "tuple"
}
],
"internalType": "struct Identity.IdentityInfo",
"name": "info",
"type": "tuple"
}
],
"internalType": "struct Identity.Registration",
"name": "",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "regIndex",
"type": "uint32"
},
{
"internalType": "address",
"name": "target",
"type": "address"
},
{
"components": [
{
"internalType": "bool",
"name": "isUnknown",
"type": "bool"
},
{
"internalType": "bool",
"name": "isFeePaid",
"type": "bool"
},
{
"internalType": "uint256",
"name": "feePaidDeposit",
"type": "uint256"
},
{
"internalType": "bool",
"name": "isReasonable",
"type": "bool"
},
{
"internalType": "bool",
"name": "isKnownGood",
"type": "bool"
},
{
"internalType": "bool",
"name": "isOutOfDate",
"type": "bool"
},
{
"internalType": "bool",
"name": "isLowQuality",
"type": "bool"
},
{
"internalType": "bool",
"name": "isErroneous",
"type": "bool"
}
],
"internalType": "struct Identity.Judgement",
"name": "judgement",
"type": "tuple"
},
{
"internalType": "bytes32",
"name": "identity",
"type": "bytes32"
}
],
"name": "provideJudgement",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "quitSub",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "registrars",
"outputs": [
{
"components": [
{
"internalType": "bool",
"name": "isValid",
"type": "bool"
},
{
"internalType": "uint32",
"name": "index",
"type": "uint32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "uint256",
"name": "fee",
"type": "uint256"
},
{
"components": [
{
"internalType": "bool",
"name": "display",
"type": "bool"
},
{
"internalType": "bool",
"name": "legal",
"type": "bool"
},
{
"internalType": "bool",
"name": "web",
"type": "bool"
},
{
"internalType": "bool",
"name": "riot",
"type": "bool"
},
{
"internalType": "bool",
"name": "email",
"type": "bool"
},
{
"internalType": "bool",
"name": "pgpFingerprint",
"type": "bool"
},
{
"internalType": "bool",
"name": "image",
"type": "bool"
},
{
"internalType": "bool",
"name": "twitter",
"type": "bool"
}
],
"internalType": "struct Identity.IdentityFields",
"name": "fields",
"type": "tuple"
}
],
"internalType": "struct Identity.Registrar[]",
"name": "",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "sub",
"type": "address"
}
],
"name": "removeSub",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "sub",
"type": "address"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "data",
"type": "tuple"
}
],
"name": "renameSub",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "regIndex",
"type": "uint32"
},
{
"internalType": "uint256",
"name": "maxFee",
"type": "uint256"
}
],
"name": "requestJudgement",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "regIndex",
"type": "uint32"
},
{
"internalType": "address",
"name": "newAccount",
"type": "address"
}
],
"name": "setAccountId",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "regIndex",
"type": "uint32"
},
{
"internalType": "uint256",
"name": "fee",
"type": "uint256"
}
],
"name": "setFee",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "regIndex",
"type": "uint32"
},
{
"components": [
{
"internalType": "bool",
"name": "display",
"type": "bool"
},
{
"internalType": "bool",
"name": "legal",
"type": "bool"
},
{
"internalType": "bool",
"name": "web",
"type": "bool"
},
{
"internalType": "bool",
"name": "riot",
"type": "bool"
},
{
"internalType": "bool",
"name": "email",
"type": "bool"
},
{
"internalType": "bool",
"name": "pgpFingerprint",
"type": "bool"
},
{
"internalType": "bool",
"name": "image",
"type": "bool"
},
{
"internalType": "bool",
"name": "twitter",
"type": "bool"
}
],
"internalType": "struct Identity.IdentityFields",
"name": "fields",
"type": "tuple"
}
],
"name": "setFields",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"components": [
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "key",
"type": "tuple"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "value",
"type": "tuple"
}
],
"internalType": "struct Identity.Additional[]",
"name": "additional",
"type": "tuple[]"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "display",
"type": "tuple"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "legal",
"type": "tuple"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "web",
"type": "tuple"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "riot",
"type": "tuple"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "email",
"type": "tuple"
},
{
"internalType": "bool",
"name": "hasPgpFingerprint",
"type": "bool"
},
{
"internalType": "bytes",
"name": "pgpFingerprint",
"type": "bytes"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "image",
"type": "tuple"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "twitter",
"type": "tuple"
}
],
"internalType": "struct Identity.IdentityInfo",
"name": "info",
"type": "tuple"
}
],
"name": "setIdentity",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "data",
"type": "tuple"
}
],
"internalType": "struct Identity.SubAccount[]",
"name": "subs",
"type": "tuple[]"
}
],
"name": "setSubs",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "who",
"type": "address"
}
],
"name": "subsOf",
"outputs": [
{
"components": [
{
"internalType": "uint256",
"name": "deposit",
"type": "uint256"
},
{
"internalType": "address[]",
"name": "accounts",
"type": "address[]"
}
],
"internalType": "struct Identity.SubsOf",
"name": "",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "who",
"type": "address"
}
],
"name": "superOf",
"outputs": [
{
"components": [
{
"internalType": "bool",
"name": "isValid",
"type": "bool"
},
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"components": [
{
"internalType": "bool",
"name": "hasData",
"type": "bool"
},
{
"internalType": "bytes",
"name": "value",
"type": "bytes"
}
],
"internalType": "struct Identity.Data",
"name": "data",
"type": "tuple"
}
],
"internalType": "struct Identity.SuperOf",
"name": "",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
}
]
有了ABI后,您可以根据您的选择使用以太坊库与预编译交互。一般情况下,您需要执行以下步骤:
- 创建 provider
- 创建Identity Precompile的合约实例
- 与Identity Precompile的函数交互
在下方示例中,您将了解如何组合设置身份所需的数据、如何设置身份以及如何在设置身份信息后检索身份信息。
请记住
以下代码片段仅用于操作演示。请勿将您的私钥存储与JavaScript或Python文件中。
import { ethers } from 'ethers'; // Import Ethers library
import ABI from './identityPrecompileABI.js'; // Import Identity Precompile ABI
const privateKey = 'INSERT_PRIVATE_KEY';
const identityPrecompileAddress = '0x0000000000000000000000000000000000000818';
// Create Ethers provider and signer
const provider = new ethers.JsonRpcProvider(
'https://rpc.api.moonbase.moonbeam.network'
);
const signer = new ethers.Wallet(privateKey, provider);
// Create interface for the Identity Precompile
const identityPrecompile = new ethers.Contract(
identityPrecompileAddress,
ABI,
signer
);
// Interact with the Precompile Registry
const setIdentity = async () => {
// Assemble identity info
const identityInfo = {
additional: [],
display: {
hasData: true,
value: '0x416c696365', // Alice in hex
},
legal: {
hasData: false,
value: '0x',
},
web: {
hasData: false,
value: '0x',
},
riot: {
hasData: false,
value: '0x',
},
email: {
hasData: false,
value: '0x',
},
hasPgpFingerprint: false,
pgpFingerprint: '0x',
image: {
hasData: false,
value: '0x',
},
twitter: {
hasData: false,
value: '0x',
},
};
// Set the identity
const submitIdentity = await identityPrecompile.setIdentity(identityInfo);
console.log(`Identity set. Transaction hash: ${submitIdentity.hash}`);
// Retrieve the identity
const identity = await identityPrecompile.identity(signer.address);
console.log(`Identity is valid: ${identity[0]}`);
console.log(`Judgements provided for this identity: ${identity[1]}`);
console.log(`Deposit paid for this identity: ${identity[2]}`);
console.log(`Identity information: ${identity[3]}`);
console.log(`Display name: ${ethers.toUtf8String(identity[3][1][1])}`);
};
setIdentity();
import { Web3 } from 'web3';
import ABI from './identityPrecompileABI.js'; // Import Identity Precompile ABI
const from = {
privateKey: 'INSERT_PRIVATE_KEY',
address: 'INSERT_ADDRESS',
};
const identityPrecompileAddress = '0x0000000000000000000000000000000000000818';
// Create provider
const web3 = new Web3('https://rpc.api.moonbase.moonbeam.network');
// Create interface for the Identity Precompile
const identityPrecompile = new web3.eth.Contract(
ABI,
identityPrecompileAddress,
{ from: from.address }
);
// Interact with the Precompile Registry
const setIdentity = async () => {
// Assemble identity info
const identityInfo = {
additional: [],
display: {
hasData: true,
value: '0x416c696365', // Alice in hex
},
legal: {
hasData: false,
value: '0x',
},
web: {
hasData: false,
value: '0x',
},
riot: {
hasData: false,
value: '0x',
},
email: {
hasData: false,
value: '0x',
},
hasPgpFingerprint: false,
pgpFingerprint: '0x',
image: {
hasData: false,
value: '0x',
},
twitter: {
hasData: false,
value: '0x',
},
};
// Set the identity
const submitIdentity = await identityPrecompile.methods.setIdentity(
identityInfo
);
const sendTransaction = await web3.eth.accounts.signTransaction(
{
to: identityPrecompileAddress,
data: submitIdentity.encodeABI(),
gas: await submitIdentity.estimateGas(),
gasPrice: await web3.eth.getGasPrice(),
nonce: await web3.eth.getTransactionCount(from.address),
},
from.privateKey
);
// Sign and send the transaction to set the identity
const createReceipt = await web3.eth.sendSignedTransaction(
sendTransaction.rawTransaction
);
console.log(
`Identity set. Transaction hash: ${createReceipt.transactionHash}`
);
// Retrieve the identity
const identity = await identityPrecompile.methods.identity(address).call();
console.log(`Identity is valid: ${identity[0]}`);
console.log(`Judgements provided for this identity: ${identity[1]}`);
console.log(`Deposit paid for this identity: ${identity[2]}`);
console.log(`Identity information: ${identity[3]}`);
console.log(`Display name: ${web3.utils.hexToUtf8(identity[3][1][1])}`);
};
setIdentity();
from web3 import Web3
# Paste or import the Identity Precompile ABI
abi = "INSERT_IDENTITY_PRECOMPILE_ABI"
account_from = {
"private_key": "INSERT_PRIVATE_KEY",
"address": "INSERT_ADDRESS",
}
identity_precompile_address = "0x0000000000000000000000000000000000000818"
# Create provider
web3 = Web3(Web3.HTTPProvider("https://rpc.api.moonbase.moonbeam.network"))
# Create interface for the Precompile Registry
identity_precompile = web3.eth.contract(address=identity_precompile_address, abi=abi)
def set_identity():
# Assemble identity info
identity_info = {
"additional": [],
"display": {
"hasData": True,
"value": "0x416c696365", # Alice in hex
},
"legal": {
"hasData": False,
"value": "0x",
},
"web": {
"hasData": False,
"value": "0x",
},
"riot": {
"hasData": False,
"value": "0x",
},
"email": {
"hasData": False,
"value": "0x",
},
"hasPgpFingerprint": False,
"pgpFingerprint": "0x",
"image": {
"hasData": False,
"value": "0x",
},
"twitter": {
"hasData": False,
"value": "0x",
},
}
# Set the identity
submit_identity = identity_precompile.functions.setIdentity(
identity_info
).build_transaction(
{
"from": Web3.to_checksum_address(account_from["address"]),
"nonce": web3.eth.get_transaction_count(
Web3.to_checksum_address(account_from["address"])
),
}
)
# Sign and send the transaction to set the identity
tx_create = web3.eth.account.sign_transaction(
submit_identity, account_from["private_key"]
)
tx_hash = web3.eth.send_raw_transaction(tx_create.rawTransaction)
tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
print(f"Identity set. Transaction hash: { tx_receipt.transactionHash.hex() }")
# Retrieve the identity
identity = identity_precompile.functions.identity(account_from["address"]).call()
print(f"Identity is valid: { identity[0] }")
print(f"Judgements provided for this identity: { identity[1] }")
print(f"Deposit paid for this identity: { identity[2] }")
print(f"Identity information: { identity[3] }")
print(f"Display name: { web3.to_text(identity[3][1][1]) }")
set_identity()
| Created: December 4, 2023