Criar e Implantar Contrato Inteligente NFT
Nesta seção, você aprenderá a criar e implantar um contrato inteligente NFT que é necessário para configurar o NFT Marketplace.
Use o Blockchain App Builder para gerar um contrato inteligente para gerenciar minting, propriedade e transferência de NFTs. O capacitador principal dessa solução é a capacidade de mint e transferir NFTs usando o Oracle Blockchain Platform.
Primeiro você cria um arquivo de especificação NFT e, em seguida, implanta o contrato inteligente em uma instância do Oracle Blockchain Platform. Em seguida, você pode testar o contrato inteligente.
Instalar o Blockchain App Builder
Depois de provisionar uma instância do Oracle Blockchain Platform, conclua as seguintes etapas:
- Na console do Oracle Blockchain Platform, abra a guia Ferramentas do Desenvolvedor e selecione o painel Blockchain App Builder.
- Na seção Fazer Download, faça download do arquivo de ferramentas da interface de linha de comando (CLI) ou da extensão de Código do Visual Studio (VS) e, em seguida, configure-o localmente.
Personalizar o Arquivo de Especificação NFT de Amostra
Um exemplo de arquivo de especificação NFT está incluído no Blockchain App Builder. Você pode usá-lo e adaptá-lo às suas necessidades, como mostrado no seguinte exemplo:
assets:
- name: ArtCollection
type: token
symbol: ART #mandatory
standard: erc721+
anatomy:
type: nonfungible
unit: whole
behavior:
- indivisible # mandatory
- singleton # mandatory
- mintable: # mandatory
max_min_quantity: 20000
- transferable
- burnable
- roles:
minter_role_name: minter
properties:
- name: price
type: number
- name: on_sale_flag
type: boolean
metadata:
- name: painting_name
type: string
- name: description
type: string
- name: image
type: string
- name: painter_name
type: string
customMethods:
- executeQuery
- "createAccountByConsumers(org_id: string, user_id: string, token_type: string)" # Create accounts for consumers while signing up
- "sell(token_id: string, selling_price: number)" # Post the token for selling in the marketplace
- "buyWithTokens(from_org_id: string, from_user_id: string, to_org_id: string, to_user_id: string, nonfungible_token_id: string, fungible_token_id: string, amount_paid: number)" # Buy the NFT after paying the using FT Tokens
- "buyWithDirectPayment(from_org_id: string, from_user_id: string, to_org_id: string, to_user_id: string, nonfungible_token_id: string, amount_paid: number)" # Buy the NFT after paying the amount using payment gateway
Você pode adicionar propriedades e métodos personalizados para estender esta especificação para chaincode NFT. Os nós de cadeia NFT gerados pelo Blockchain App Builder são baseados no padrão ERC-721
.
Para gerar o chaincode (contrato inteligente) usando a extensão Visual Studio Code, conclua as seguintes etapas:
- Na seção Chaincodes, clique no ícone +. O painel Detalhes do Codificação é aberto.
- Preencha os campos obrigatórios para gerar o projeto chaincode:
- Informe um nome para o projeto chaincode.
- Selecione
TypeScript
ouGo
como o idioma no qual os métodos de chaincode serão gerados. - Selecione o arquivo de especificação de entrada criado anteriormente.
- Insira o local onde deseja que o projeto seja gerado.
- Clique em Criar.
A captura de tela a seguir da IU mostra a janela Criar Chaincode.

Descrição da ilustração blockchain_chaincode_details.png
src
na hierarquia do projeto.
- O arquivo de modelo contém todas as estruturas de dados geradas que representam o token, as contas etc.
- O arquivo do controlador contém todos os métodos de ciclo de vida NFT gerados e funções de suporte com a lógica de validação necessária com base na especificação.
/**
*
* BDB sql rich queries can be executed in OBP CS/EE.
* This method can be invoked only when connected to remote OBP CS/EE network.
*
*/
@Validator(yup.string())
public async executeQuery(query: string) {
const result = await this.query(query);
return result;
}
@Validator(yup.string(), yup.string(), yup.string())
public async createAccountByConsumers(org_id: string, user_id: string, token_type: string) {
//await this.Ctx.ERC721Auth.checkAuthorization('ERC721ACCOUNT.createAccount', 'TOKEN');
return await this.Ctx.ERC721Account.createAccount(org_id, user_id, token_type);
}
@Validator(yup.string(), yup.number())
public async sell (token_id: string, selling_price: number) {
try {
const token = await this.Ctx.ERC721Token.get(token_id);
const t = new ArtCollection(token)
t.price = selling_price;
t.on_sale_flag = true;
//console.log(token);
await this.Ctx.ERC721Token.update(t);
return `Token ID : '${token_id}' has been posted for selling in the marketplace'`;
} catch(error) {
throw new Error(error.message);
}
}
@Validator(yup.string(), yup.string(), yup.string(), yup.string(), yup.string(), yup.string(), yup.number())
public async buyWithTokens(from_org_id: string, from_user_id: string, to_org_id: string, to_user_id: string, nonfungible_token_id: string, fungible_token_id: string, amount_paid: number) {
try {
const token = await this.Ctx.ERC721Token.get(nonfungible_token_id);
const t = new ArtCollection(token);
const oChainUtil = new OChainUtils(this.Ctx.Stub);
var msg = `Token ID : '${nonfungible_token_id}' had not been transferred'`;
if (t.on_sale_flag==true) {
if(t.price == amount_paid) {
// @ts-ignore
await oChainUtil.invokeChaincode("LoyaltyToken7", "transferTokens", [fungible_token_id, from_org_id, from_user_id, amount_paid], "marketplace");
const from_account_id = await this.Ctx.ERC721Account.generateAccountId(from_org_id, from_user_id);
const to_account_id = await this.Ctx.ERC721Account.generateAccountId(to_org_id, to_user_id);
await this.Ctx.ERC721Token.transferFrom(from_account_id, to_account_id, t);
msg = `Token ID : '${nonfungible_token_id}' has been successfully transferred to UserID : '${to_user_id}'`;
}
}
else {
msg = `Token ID : '${nonfungible_token_id}' has not been transferred to UserID : '${to_user_id}' as the amount was not fully paid'`;
}
return msg;
} catch(error)
{
throw new Error(error.message);
}
}
@Validator(yup.string(), yup.string(), yup.string(), yup.string(), yup.string(), yup.number())
public async buyWithDirectPayment(from_org_id: string, from_user_id: string, to_org_id: string, to_user_id: string, nonfungible_token_id: string, amount_paid: number) {
try {
const token = await this.Ctx.ERC721Token.get(nonfungible_token_id);
const t = new ArtCollection(token);
var msg = `Token ID : '${nonfungible_token_id}' had not been transferred'`;
if (t.on_sale_flag==true) {
if(t.price == amount_paid) {
const from_account_id = await this.Ctx.ERC721Account.generateAccountId(from_org_id, from_user_id);
const to_account_id = await this.Ctx.ERC721Account.generateAccountId(to_org_id, to_user_id);
await this.Ctx.ERC721Token.transferFrom(from_account_id, to_account_id, t);
msg = `Token ID : '${nonfungible_token_id}' has been successfully transferred to UserID : '${to_user_id}'`;
}
}
else {
msg = `Token ID : '${nonfungible_token_id}' has not been transferred to UserID : '${to_user_id}' as the amount was not fully paid'`;
}
return msg;
} catch(error) {
throw new Error(error.message);
}
}
}
Implantar o Contrato Inteligente
Depois de criar um projeto de chaincode, você pode implantá-lo localmente.
No painel Detalhes de Codificação, selecione Implantar para abrir o assistente de implantação. O Blockchain App Builder inclui uma rede blockchain local, que é executada em contêineres Docker, que você pode usar para fins de teste.
Você também pode implantar o chaincode em uma instância do Oracle Blockchain Platform selecionando o perfil de conexão na lista para o ambiente de destino. Você também deve concluir e salvar os Parâmetros de Entrada, porque o chaincode NFT gerado requer os parâmetros orgId
e userId
para inicialização. Os parâmetros orgId
e userId
são usados para especificar quais usuários têm privilégios de administrador de token.
Testar o Contrato Inteligente
Quando o chaincode é implantado, o Oracle Blockchain Platform expõe automaticamente as APIs REST para inicialização de token, gerenciamento de conta e atribuição, e métodos de ciclo de vida NFT (criar, transferir, queimar).
Você pode testar selecionando Executar no painel Detalhes do Codificação no Construtor de Aplicativos Blockchain ou usando um cliente de API REST como Postman.
A captura de tela a seguir da IU mostra a guia Executar da janela Criar Chaincode.

Descrição da ilustração blockchain_chaincode_execute.png
Para chamar métodos de contrato inteligente do Oracle Blockchain Platform usando a API REST, use o método POST
e especifique o URL, que consiste em duas partes concatenadas juntas. A primeira parte é o ponto final do proxy REST no Oracle Blockchain Platform, que você pode obter na guia Nós da console do Oracle Blockchain Platform.
A segunda parte é o URI específico para chamar a transação usando a API Transaction. Consulte a documentação para enviar uma solicitação POST
. As duas partes formam um URL completo semelhante ao aqui.
https://oabcs1-iad.blockchain.ocp.oraclecloud.com:7443/restproxy/api/v2/channels/{channelName}/transactions
Substitua {channelName}
pelo nome do canal especificado ao implantar seu chaincode, como marketplace. Ao construir a solicitação de API, conclua as seguintes etapas:
- Defina a autorização para usar
Basic Auth
com ouserid and password
especificado que está mapeado para a atribuiçãoREST_Client
. Você também pode usar tokensOAuth2
. Consulte Usar Autenticação Baseada em Token de Acesso OAuth 2.0 no guia da API REST para obter mais informações. - Defina o cabeçalho
Content-Type
comoapplication/json
. - No corpo da solicitação, inclua os parâmetros necessários para a chamada da transação, incluindo o nome do chaincode e o método
create<TokenName>Token
junto com os argumentos necessários.
Com base no chaincode gerado pelo modelo yaml
, o texto a seguir mostra um corpo de solicitação de amostra e a resposta associada.
Solicitação
{
"chaincode": "{{NFTChaincode}}",
"args": [
"createArtCollectionToken",
"{\"token_id\":\"{{NFTTokenID}}\",\"token_uri\":\"https://ipfs.io/ipfs/QmV68aiT7xw2WX8pmDbeTWpGP2or35NUFan9RagymsLpgV?filename=ArtCollection_NFT1.json\",\"metadata\":{\"painting_name\":\"Oracle - Red Bull Partnership\",\"image\":\"https://ipfs.io/ipfs/QmVap6Gkh3Cp9DiLLWvkvJHpuXpFmYB2GzU1caM57gNcAa?filename=Oracle_RedBull_NFT1.jpeg\",\"painter\":\"Alex\"},\"price\":200,\"on_sale_flag\":false}"
],
"timeout": 0,
"sync": true
}
Resposta
{
"returnCode": "Success",
"error": "",
"result": {
"txid": "c999922f04c3011bf25ca43624e4bb23e8900634f8e23a1648170a90274a9733",
"payload": {
"metadata": {
"painter": "Alex",
"painting_name": "Oracle - Red Bull Partnership",
"image": "https://ipfs.io/ipfs/QmVap6Gkh3Cp9DiLLWvkvJHpuXpFmYB2GzU1caM57gNcAa?filename=Oracle_RedBull_NFT1.jpeg"
},
"assetType": "otoken",
"created_by": "oaccount~eadf1b0ae857164f8681d1742b6328089a7d33ebec76d8248cb909da7a84f42a",
"creation_date": "2022-04-28T12:08:38.000Z",
"owner": "oaccount~eadf1b0ae857164f8681d1742b6328089a7d33ebec76d8248cb909da7a84f42a",
"uri": "https://ipfs.io/ipfs/QmV68aiT7xw2WX8pmDbeTWpGP2or35NUFan9RagymsLpgV?filename=ArtCollection_NFT1.json",
"is_burned": false,
"token_id": "NFT17",
"token_name": "artcollection",
"symbol": "ART",
"token_standard": "erc721+",
"token_type": "nonfungible",
"token_unit": "whole",
"behaviors": [
"indivisible",
"singleton",
"mintable",
"transferable",
"burnable",
"roles"
],
"roles": {
"minter_role_name": "minter"
},
"mintable": {
"max_mint_quantity": 20000
},
"token_uri": "https://ipfs.io/ipfs/QmV68aiT7xw2WX8pmDbeTWpGP2or35NUFan9RagymsLpgV?filename=ArtCollection_NFT1.json",
"price": 200,
"on_sale_flag": false
},
Consulte a seção Explorar Mais para obter mais informações sobre os métodos disponíveis para gerenciar códigos de cadeia NFT, incluindo os métodos Golang
ou TypeScript
e Platform REST API
.
Você pode chamar as APIs diretamente do webhook do Oracle Content Management e do aplicativo web criado no Visual Builder Cloud Service (VBCS), ou remapear e encapsulá-las com o gateway de API para uso por um aplicativo web do marketplace hospedado externamente. Observe que quando você cria (mint) um NFT, um dos parâmetros que deve ser fornecido é token_uri
, que pode ser um IPFS URI
apontando para um arquivo JSON
que representa o objeto digital.
https://ipfs.io/ipfs/QmV68aiT7xw2WX8pmDbeTWpGP2or35NUFan9RagymsLpgV?filename=ArtCollection_NFT1.json
As etapas a seguir descrevem um exemplo de geração do URI do token usando o IPFS Desktop:
- Faça upload de um arquivo de imagem em
IPFS
e salve o URI da imagem. - Crie e faça upload do arquivo
JSON
que inclua o URI da imagem junto com os campos de metadados relevantes. - Compartilhe e copie o link para o arquivo
JSON
sob o ... Mais lista.
{
"painting_name": "Oracle - Red Bull Partnership",
"description": "Cloud Partnership",
"image": "https://ipfs.io/ipfs/QmVap6Gkh3Cp9DiLLWvkvJHpuXpFmYB2GzU1caM57gNcAa?filename=Oracle_RedBull.jpeg",
"painter_name": "Alex"
}
Use o URI que aponta para o arquivo JSON
para o parâmetro token_uri
.
Você também pode incluir metadados relevantes nos atributos passados para o método create<Token-Name>Token
, que manterão os metadados no razão do Oracle Blockchain Platform para fácil recuperação.
Para NFTs criados usando o OCM (Oracle Content Management), use o webhook do OCM para chamar o Oracle Functions usando um Gateway de API e colocar a chamada de API REST no Oracle Functions conforme mostrado no diagrama de arquitetura. Você também pode chamar APIs REST do Blockchain diretamente do aplicativo web marketplace ou usando um mapeamento de gateway de API para suportar conteúdo gerado pelo usuário. A funcionalidade de negociação do Marketplace pode chamar os métodos personalizados para tratar o pagamento e, em seguida, acionar uma transferência da propriedade do NFT, como os métodos de amostra buyWithTokens
e buyWithDirectPayment
.