💠Metadados

ink! Metadata

Os metadados do ink! são usados para descrever um contrato de forma independente de linguagem. Eles são destinados a serem usados por ferramentas de terceiros (por exemplo, interfaces de usuário, exploradores de blocos) para chamar corretamente as funções do contrato e interpretar eventos.

Os metadados do ink! são gerados quando um contrato é construído usando o cargo-contract, por exemplo, cargo contract build.

Os metadados podem ser encontrados no diretório de destino do seu contrato com o nome <contract-name>.json.

NOTA: Os metadados também estão contidos no arquivo <contract-name>.contract. A diferença é que o arquivo .contract também contém o binário Wasm do seu contrato.

<contract-name>.json

Os metadados são definidos pelas seguintes chaves obrigatórias:

  • source: nformações sobre o código Wasm do contrato.

  • contract: Metadados sobre o contrato.

  • abi: JSON bruto dos metadados abi do contrato, gerados durante a compilação do contrato.

Opcionalmente, pode conter as seguintes chaves:

  • user: Metadados adicionais definidos pelo usuário.

{
  "source": {
    "hash": "...",
    "language": "...",
    "compiler": "..."
  },
  "contract": {
    "name": "...",
    "version": "...",
    "authors": [
      "..."
    ]
  },
  "spec": {
    "constructors": ["..."],
    "messages": ["..."]
  }
}

NOTA: Observe que não temos uma chave "abi", mas usamos o campo "spec" para especificar a ABI do contrato. Você pode ler mais sobre isso na documentação da ABI.

As próximas seções irão aprofundar como essas seções são compostas.

source

Este objeto contém informações sobre como o contrato foi construído.

Ele consiste nas seguintes chaves obrigatórias:

  • hash: O hash do código Wasm do contrato.

  • language: A linguagem utilizada para escrever o contrato.

  • compiler: O compilador usado para compilar o contrato.

Ele pode opcionalmente incluir as seguintes chaves:

  • wasm: O código Wasm real do contrato, para opcionalmente empacotar o código com os metadados.

  • build_info: Informações extras sobre o ambiente no qual o contrato foi construído.

"source": {
  "hash": "0x157014494527fee27a82e49bbd9eea10c0713bb0566f6def37f4595db86236ff",
  "language": "ink! 4.0.0",
  "compiler": "rustc 1.66.0"
}

INFO: Se você está interessado na referência de código do cargo-contract, consulte aqui.

contract

Este objeto contém metadados extras sobre o contrato.

As chaves obrigatórias incluem:

  • name: O nome do contrato inteligente.

  • version: A versão do contrato inteligente.

  • authors: Os autores do contrato inteligente.

Ele também pode incluir opcionalmente as seguintes chaves:

  • description: A descrição do contrato inteligente.

  • documentation: Link para a documentação do contrato inteligente.

  • repository: Link para o repositório de código do contrato inteligente.

  • homepage: Link para a página inicial do contrato inteligente.

  • license: A licença do contrato inteligente.

"contract": {
  "name": "flipper",
  "version": "4.0.0-beta.1",
  "authors": [
    "Parity Technologies <admin@parity.io>"
  ]
}

INFO Se você está interessado na referência de código de cargo-contract, veja aqui.

ABI

Esta é a especificação do contrato.

Ao contrário das seções de metadados anteriores, a estrutura do objeto armazenado aqui não é definida. Em vez disso, cabe a cada linguagem de programação (por exemplo, ink!, ask!, Solidity) definir seu próprio formato de metadados que será armazenado aqui.

Neste documento, vamos nos concentrar na ABI do ink!.

Os metadados do ink! consistem nas seguintes seções obrigatórias:

  • spec: A descrição do contrato (por exemplo, construtores, mensagens, eventos, etc.).

  • storage: A estrutura de dados de armazenamento.

  • types: Um registro somente leitura contendo os tipos em sua forma portátil para serialização.

  • version: A versão dos metadados do ink!.

"spec": { ... },
"storage": { ... },
"types": { ... },
"version": "..."

Informação: Se você está interessado na referência de código do ink!, consulte aqui.

spec

A especificação spec do contrato consiste nas seguintes chaves obrigatórias:

  • constructors: O conjunto de construtores do contrato.

    • label: O rótulo do construtor. No caso de um construtor fornecido por um traço, o rótulo é prefixado com o rótulo do traço.

    • selector: O hash do seletor da mensagem.

    • payable: Se o construtor aceita algum value do chamador.

    • default: Se o construtor é marcado como padrão, útil para interfaces de usuário.

    • args: Os parâmetros do manipulador de implantação.

    • docs: A documentação do manipulador de implantação.

  • messages: As mensagens externas do contrato.

    • label: O rótulo da mensagem. No caso de mensagens e construtores fornecidos por traços, o prefixo por convenção no ink! é o rótulo do traço.

    • selector: O hash do seletor da mensagem.

    • mutates: Se a mensagem tem permissão para modificar o estado do contrato.

    • payable: Se a mensagem aceita algum value do chamador.

    • default: Se a mensagem é marcada como padrão, útil para interfaces de usuário.

    • args: Os parâmetros da mensagem.

    • return_type: O tipo de retorno da mensagem.

    • docs: A documentação da mensagem.

  • environment: Configuração dos tipos com os quais a blockchain hospedeira opera. Você pode verificar os tipos padrão na seção Environment.

    • accountId: O tipo que descreve um endereço de conta.

    • balance: O tipo que descreve os valores de saldo.

    • blockNumber: O tipo que descreve um número de bloco.

    • chainExtension: O tipo que descreve a extensão da cadeia para o ambiente. Para obter mais informações sobre o uso e definição, verifique esta seção.

    • maxEventTopics: O número máximo de tópicos de evento suportados pelo tempo de execução.

    • timestamp: O tipo que descreve um carimbo de timestamp.

  • events: Os eventos do contrato.

    • label: O rótulo do evento.

    • args: Os argumentos do evento.

    • docs: A documentação do evento.

  • docs: A documentação do contrato.

  • lang_error: O tipo de erro específico da linguagem.

NOTA: Embora todas essas chaves sejam obrigatórias, elas podem estar vazias. Por exemplo, se um contrato não define nenhum events, a chave events conterá um array vazio [].

COMPATIBILIDADE COM O INK! 3.X

O campo lang_error foi introduzido como parte do ink! 4.0. Isso representa um erro que vem da própria linguagem de contrato inteligente, e não do contrato nem do ambiente subjacente (por exemplo, pallet-contracts).

Agora, todas as mensagens e construtores do ink! retornam um Result que usa isso como a variante Error (consulte a documentação do LangError para obter mais informações).

"spec": {
  "constructors": [
    {
      "args": [
        { ... }
      ],
      "docs": [
        "Creates a new flipper smart contract initialized with the given value."
      ],
      "label": "new",
      "payable": false,
      "default": false,
      "selector": "0x9bae9d5e"
    }
  ],
  "docs": [],
  "events": [],
  "lang_error": {
    "displayName": [
      "ink",
      "LangError"
    ],
    "type": 3
  },
  "messages": [
    {
      "args": [],
      "docs": [
        " Flips the current value of the Flipper's boolean."
      ],
      "label": "flip",
      "mutates": true,
      "payable": false,
      "default": false,
      "returnType": null,
      "selector": "0x633aa551"
    }
  ]
}

storage

Esta chave descreve o layout de armazenamento de um contrato ink!. Ela acompanha algumas das diferentes estruturas que podem ser colocadas no armazenamento.

Ela consiste nas seguintes chaves opcionais (dependendo das estruturas de dados usadas pelo contrato):

  • root: O nó raiz define a chave de armazenamento para todas as sub-árvores.

    • root_key: A chave raiz da sub-árvore.

    • layout: O layout de armazenamento dos elementos de layout não limitados.

  • leaf: O nó raiz define a chave de armazenamento para todas as sub-árvores.

    • key: A chave de deslocamento no armazenamento.

    • ty: O tipo da entidade codificada.

  • hash: Um layout que gera hashes de valores em todo o espaço de chaves de armazenamento.

    • offset: A chave de deslocamento do layout da matriz. Esta é a mesma chave que o elemento no índice 0 do layout da matriz.

    • strategy: A estratégia de hash para dispor os elementos subjacentes.

    • layout: O layout de armazenamento dos elementos de layout não limitados.

  • array: Uma matriz de células de armazenamento associadas codificadas com um determinado tipo.

    • offset: A chave de deslocamento do layout da matriz. Esta é a mesma chave que o elemento no índice 0 do layout da matriz.

    • len: O número de elementos no layout da matriz.

    • layout: O layout dos elementos armazenados no layout da matriz.

  • struct: Um layout de estrutura com campos de tipos diferentes.

    • name: O nome da estrutura.

    • fields: Os campos do layout da estrutura.

  • enum: Um layout de enumeração com um discriminante que indica qual variante é disposta.

    • name: O nome do enum.

    • dispatch_key: A chave onde o discriminante é armazenado para despachar as variantes.

    • variants: As variantes do enum.

"storage": {
  "root": {
    "layout": {
      "struct": {
        "fields": [
          {
            "layout": {
              "leaf": {
                "key": "0x00000000",
                "ty": 0
              }
            },
            "name": "value"
          }
        ],
        "name": "Flipper"
      }
    },
    "root_key": "0x00000000"
  }
}

types

Este objeto contém o registro de tipos para o contrato inteligente. Ele consiste em uma matriz de objetos de tipo, cada um dos quais é definido da seguinte forma:

  • id: ID numérico para referenciar o tipo.

  • ty: A definição do tipo.

    • path: O caminho único para o tipo. Pode estar vazio para tipos embutidos.

    • params: Os parâmetros de tipo genérico do tipo em uso. Vazio para tipos não genéricos.

    • def: A definição real do tipo.

    • docs: Documentação.

O objeto de definição de tipo (def) suporta os seguintes tipos primitive:

  • bool, char, str, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128.

Também suporta uma variedade de tipos complexos embutidos e definidos pelo usuário. No entanto, não vamos nos aprofundar neles aqui. Se você estiver interessado em saber mais, dê uma olhada no scale-info .

"types": [
  {
    "id": 0,
    "type": {
      "def": {
        "primitive": "bool"
      }
    }
  }
]

Outras partes dos metadados, como o objeto de armazenamento storage, farão referência a tipos individuais deste registro de tipos usando a chave "id".

version

Isso indica a versão do formato ABI à qual os metadados gerados estão em conformidade. Isso é distinto de qualquer conceito de versionamento de crate do Rust.

"version": "4"

NOTA DE COMPATIBILIDADE DO INK! 3.X

Na versão 3 dos metadados do ink!, a versão era especificada como uma chave que envolvia o ABI (por exemplo, "V3": { ... }). Isso não é mais o caso na versão 4.

user

Este é um campo opcional usado para adicionar metadados definidos pelo usuário. Alguns exemplos de coisas que você pode querer incluir aqui são:

  • moon_phase: Fase da lua durante a qual o smart contract funciona.

  • favorite_blockchain: A blockchain favorita dos autores do contrato (resposta: Lunes!).

Last updated