Skip to main content

Create NFTs via Portkey Account

Create collection​

1. Obtain SEED​

Refer to Obtain SEED

2. Create​

Create by using ManagerForwardCall in the AA contract and calling the CreateToken method in the agent contract.

Please note: the contract called is on the MainChain but you can decide to create NFTs whether on the MainChain or dAppChains via the parameter issue_chain_id.

var Client = new AElf.Client.AElfClient("http://node:port");
var status = Client.GetChainStatusAsync().GetAwaiter().GetResult();
var height = status.BestChainHeight;
var blockHash = status.BestChainHash;

// Construct parameter
var createTokenInput = new AElf.Contracts.AgentInterface.ManagerCreateTokenInput()
{
Symbol = "NFTSYMBOL-0",
SeedSymbol = "SEED-1",
Memo = "MEMO_DATA",
TokenName = "NFT_COLLECTION_NAME",
TotalSupply = 1,
Decimals = 0,
Issuer = Address.FromBase58(ISSUER_ADDRESS),
IsBurnable = false,
LockWhiteList = { },
IssueChainId = ISSUE_CHAIN_ID,
ExternalInfo = { }
};

// Construct the ManagerForwardCall parameter of the AA contract
var managerForwardCallParam = new Portkey.Contracts.CA.ManagerForwardCallInput()
{
CaHash = Hash.LoadFromHex(CA_HASH),
ContractAddress = Address.FromBase58(AGENT_INTERFACE_CONTRACT_ADDRESS),
MethodName = "CreateToken",
Args = createTokenInput.ToByteString()
};

// Construct transaction
var transaction = new AElf.Types.Transaction()
{
From = Address.FromBase58(YOUR_AA_MANAGER_ADDRESS),
To = Address.FromBase58(PORTKEY_AA_CONTRACT_ADDRESS),
MethodName = "ManagerForwardCall",
Params = managerForwardCallParam.ToByteString(),
RefBlockNumber = height,
RefBlockPrefix = ByteString.CopyFrom(Hash.LoadFromHex(blockHash).Value.Take(4).ToArray()),
};

// Sign
var transactionId = HashHelper.ComputeFrom(transaction.ToByteArray());
var signature = CryptoHelper.SignWithPrivateKey(ByteArrayHelper.HexStringToByteArray(PRIVATE_KEY), transactionId.ToByteArray());

// Send transaction
await Client.SendRawTransactionAsync(new AElf.Client.Dto.SendRawTransactionInput()
{
Transaction = transaction.ToByteArray().ToHex(),
Signature = signature.ToHex(),
ReturnTransaction = true
});

3. Obtain ProxyAccountHash​

Obtain the ProxyAccountAddress of the Issuer or owner :

Call the GetTokenInfo method in the Token contract to obtain details about the collection

// Create AELF-client and obtain the current block info
var Client = new AElfClient("http://node:port");
var status = Client.GetChainStatusAsync().GetAwaiter().GetResult();
var height = status.BestChainHeight;
var blockHash = status.BestChainHash;

// Construct parameter
var getTokenInfoParam = new AElf.Contracts.MultiToken.GetTokenInfoInput()
{
Symbol = "NFTSYMBOL-0"
};

// Construct transaction
var transaction = new AElf.Types.Transaction()
{
From = Address.FromBase58(YOUR_AELF_ADDRESS),
To = Address.FromBase58(TOKEN_CONTRACT_ADDRESS),
MethodName = "GetTokenInfo",
Params = getTokenInfoParam.ToByteString(),
RefBlockNumber = height,
RefBlockPrefix = ByteString.CopyFrom(Hash.LoadFromHex(blockHash).Value.Take(4).ToArray()),
};

// Sign
var transactionId = HashHelper.ComputeFrom(transaction.ToByteArray());
var signature = CryptoHelper.SignWithPrivateKey(ByteArrayHelper.HexStringToByteArray(USER_PRIVATE_KEY), transactionId.ToByteArray());

// Send transaction
var callResult = await Client.ExecuteRawTransactionAsync(new ExecuteRawTransactionDto()
{
RawTransaction = transaction.ToByteArray().ToHex(),
Signature = signature.ToHex(),
});

Obtain ProxyAccountHash

Check the ProxyAccountHash corresponding to ProxyAccountAddress by calling the ProxyAccount contract

// Create AELF-client and obtain the current block info
var Client = new AElfClient("http://node:port");
var status = Client.GetChainStatusAsync().GetAwaiter().GetResult();
var height = status.BestChainHeight;
var blockHash = status.BestChainHash;

// Construct parameter
var getAddressParam = Address.FromBase58("PROXY_ACCOUNT_ADDRESS");

// Construct transaction
var transaction = new AElf.Types.Transaction()
{
From = Address.FromBase58(YOUR_AELF_ADDRESS),
To = Address.FromBase58(PROXY_ACCOUNT_CONTRACT_ADDRESS),
MethodName = "GetProxyAccountByProxyAccountAddress",
Params = getAddressParam.ToByteString(),
RefBlockNumber = height,
RefBlockPrefix = ByteString.CopyFrom(Hash.LoadFromHex(blockHash).Value.Take(4).ToArray()),
};

// Sign
var transactionId = HashHelper.ComputeFrom(transaction.ToByteArray());
var signature = CryptoHelper.SignWithPrivateKey(ByteArrayHelper.HexStringToByteArray(USER_PRIVATE_KEY), transactionId.ToByteArray());

// Send transaction
var callResult = await Client.ExecuteRawTransactionAsync(new ExecuteRawTransactionDto()
{
RawTransaction = transaction.ToByteArray().ToHex(),
Signature = signature.ToHex(),
});

Create NFT item​

1. Create item​

Create by using ManagerForwardCall in the AA contract, calling the ForwardCall method in the ProxyAccount contract, and calling the Token contract via the ProxyAccount contract.

Please note: the contract called is on the MainChain but you can decide to create NFTs whether on the MainChain or dAppChains via the parameter issue_chain_id.

var Client = new AElf.Client.AElfClient("http://node:port");
var status = Client.GetChainStatusAsync().GetAwaiter().GetResult();
var height = status.BestChainHeight;
var blockHash = status.BestChainHash;

// Construct the Create parameter of the Token contract
var createInput = new AElf.Contracts.MultiToken.CreateInput()
{
Symbol = "NFTSYMBOL-1",
TokenName = "NFT_TOKEN_NAME",
TotalSupply = 1,
Decimals = 0,
Issuer = Address.FromBase58("ISSUER_ADDRESS"),
IsBurnable = false,
LockWhiteList = { },
IssueChainId = ISSUE_CHAIN_ID,
};

// Construct the ForwardCall parameter of the ProxyAccount contract
var forwardCallParam = new AElf.Contracts.ProxyAccountContract.ForwardCallInput()
{
ProxyAccountHash = Hash.LoadFromHex(PROXY_ACCOUNT_ADDRESS),
ContractAddress = Address.FromBase58(TOKEN_CONTRACT_ADDRESS),
MethodName = "Create",
Args = createInput.ToByteString()
};

// Construct the ManagerForwardCall parameter of the AA contract
var managerForwardCallParam = new Portkey.Contracts.CA.ManagerForwardCallInput()
{
CaHash = Hash.LoadFromHex(AA_HASH),
ContractAddress = Address.FromBase58(AGENT_INTERFACE_CONTRACT_ADDRESS),
MethodName = "ForwardCall",
Args = forwardCallParam.ToByteString()
};

// Construct transaction
var transaction = new AElf.Types.Transaction()
{
From = Address.FromBase58(YOUR_AA_MANAGER_ADDRESS),
To = Address.FromBase58(PORTKEY_AA_CONTRACT_ADDRESS),
MethodName = "ManagerForwardCall",
Params = managerForwardCallParam.ToByteString(),
RefBlockNumber = height,
RefBlockPrefix = ByteString.CopyFrom(Hash.LoadFromHex(blockHash).Value.Take(4).ToArray()),
};

// Sign
var transactionId = HashHelper.ComputeFrom(transaction.ToByteArray());
var signature = CryptoHelper.SignWithPrivateKey(ByteArrayHelper.HexStringToByteArray(PRIVATE_KEY), transactionId.ToByteArray());

// Send transaction
await Client.SendRawTransactionAsync(new AElf.Client.Dto.SendRawTransactionInput()
{
Transaction = transaction.ToByteArray().ToHex(),
Signature = signature.ToHex(),
ReturnTransaction = true
});

2. Issue​

Issue by using ManagerForwardCall in the AA contract, calling the ForwardCall method in the ProxyAccount contract, and calling the Token contract via the ProxyAccount contract.

var Client = new AElf.Client.AElfClient("http://node:port");
var status = Client.GetChainStatusAsync().GetAwaiter().GetResult();
var height = status.BestChainHeight;
var blockHash = status.BestChainHash;

// Construct the Create parameter of the Token contract
var issueParam = new IssueInput()
{
Symbol = "NFTSYMBOL-1",
Amount = 1,
To = Address.FromBase58(ISSUE_TO_ADDRESS)
};

// Construct the ForwardCall parameter of the ProxyAccount contract
var forwardCallParam = new AElf.Contracts.ProxyAccountContract.ForwardCallInput()
{
ProxyAccountHash = Hash.LoadFromHex(PROXY_ACCOUNT_ADDRESS),
ContractAddress = Address.FromBase58(TOKEN_CONTRACT_ADDRESS),
MethodName = "Issue",
Args = issueParam.ToByteString()
};

// Construct the ManagerForwardCall parameter of the AA contract
var managerForwardCallParam = new Portkey.Contracts.CA.ManagerForwardCallInput()
{
CaHash = Hash.LoadFromHex(AA_HASH),
ContractAddress = Address.FromBase58(AGENT_INTERFACE_CONTRACT_ADDRESS),
MethodName = "ForwardCall",
Args = forwardCallParam.ToByteString()
};

// Construct transaction
var transaction = new AElf.Types.Transaction()
{
From = Address.FromBase58(YOUR_AA_MANAGER_ADDRESS),
To = Address.FromBase58(PORTKEY_AA_CONTRACT_ADDRESS),
MethodName = "ManagerForwardCall",
Params = managerForwardCallParam.ToByteString(),
RefBlockNumber = height,
RefBlockPrefix = ByteString.CopyFrom(Hash.LoadFromHex(blockHash).Value.Take(4).ToArray()),
};

// Sign
var transactionId = HashHelper.ComputeFrom(transaction.ToByteArray());
var signature = CryptoHelper.SignWithPrivateKey(ByteArrayHelper.HexStringToByteArray(PRIVATE_KEY), transactionId.ToByteArray());

// Send transaction
await Client.SendRawTransactionAsync(new AElf.Client.Dto.SendRawTransactionInput()
{
Transaction = transaction.ToByteArray().ToHex(),
Signature = signature.ToHex(),
ReturnTransaction = true
});

Process of Portkey account creating collections and NFTs​

AA operation --- set MainChain as issue_chain_id​

create-collections-use-portkey-mainchain

AA operation --- set dAppChain as issue_chain_id​

Operations on the dAppChain can only take effect when the MainChain and dAppChain are synchronized.

create-collections-use-portkey-sidechain