如何让我的 NFT 在 NEAR 钱包(AssemblyScript)中可见?

How can I make my NFT visible in the NEAR wallet (AssemblyScript)?

我正在尝试实现我自己的 NFT-contract、following this tutorial on NEAR, and the Non-Fungible Token (NEP-171) specifications。教程在 Rust 中,但我正在尝试用 AssemblyScript 做一些类似的事情。我想如果我用正确的名称和签名实现这些方法,NEAR 钱包就可以在我的 NFT-contract 上调用相应的方法(例如 nft_tokens_for_owner)。我只是想知道我是否遗漏了什么,或者我是否对它应该如何工作有错误的理解。

我已经铸造了一个 NFT-token,使用我合约中的 nft_mint 方法,使用我自己的测试网帐户。可以找到交易 here。但是,NFT 没有显示在我的测试网钱包的“收藏品”选项卡中。

我的合同(index.ts)是这样的:

import { PersistentMap } from 'near-sdk-as';
import { Token, TokenMetadata } from './reit-token';

@nearBindgen
class NFTContractMetadata {
  spec: string; // required, essentially a version like "nft-1.0.0"
  name: string; // required, ex. "Mochi Rising — Digital Edition" or "Metaverse 3"
  symbol: string; // required, ex. "MOCHI"
  icon: string | null; // Data URL
  base_uri: string | null; // Centralized gateway known to have reliable access to decentralized storage assets referenced by `reference` or `media` URLs
  reference: string | null; // URL to a JSON file with more info
  reference_hash: string | null; // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included.
}

@nearBindgen
export class Contract {
  //keeps track of the metadata for the contract
  metadata: NFTContractMetadata = {
    spec: 'reit-token-0.0.0',
    name: 'Reit Token',
    symbol: 'REIT',
    icon: null,
    base_uri: null,
    reference: null,
    reference_hash: null,
  };

  //contract owner
  owner_id: string; // Not sure if this is relevant for the contract itself

  //keeps track of all the token IDs for a given account
  tokens_per_owner: PersistentMap<string, Array<string>> = new PersistentMap<
    string,
    Array<string>
  >('tokens_pr_owner');

  //keeps track of the token struct for a given token ID
  tokens_by_id: PersistentMap<string, Token> = new PersistentMap<string, Token>(
    'tokens_by_id'
  );

  //keeps track of the token metadata for a given token ID
  token_metadata_by_id: PersistentMap<string, TokenMetadata> =
    new PersistentMap<string, TokenMetadata>('token_metadata_by_id');

  nft_tokens_for_owner(account_id: string): Array<Token> {
    const tokenIds: string[] = this.tokens_per_owner.getSome(account_id);

    const tokens: Array<Token> = new Array<Token>();
    for (let i = 0; i < tokenIds.length; ++i) {
      const token: Token = this.tokens_by_id.getSome(tokenIds[i]);
      tokens.push(token);
    }
    return tokens;
  }

  nft_mint(
    token_id: string,
    metadata: TokenMetadata,
    receiver_id: string
  ): void {
    // assert(
    //   this.tokens_by_id.contains(token_id),
    //   'ID is already taken, create new ID'
    // );
    const token = new Token(token_id, metadata, receiver_id);
    const tokens: Array<string> = new Array<string>();
    tokens.push(token_id);
    this.tokens_per_owner.set(receiver_id, tokens);
    this.tokens_by_id.set(token_id, token);
    this.token_metadata_by_id.set(token_id, token.metadata);
  }

里面reit-token.ts

import { ContractPromise } from 'near-sdk-as';
// implementation based on NEP-171
// https://nomicon.io/Standards/NonFungibleToken/Core.html

@nearBindgen
export class TokenMetadata {
  title: string; // ex. "Arch Nemesis: Mail Carrier" or "Parcel #5055"
  description: string; // free-form description
  media: string; // URL to associated media, preferably to decentralized, content-addressed storage
  media_hash: string; // Base64-encoded sha256 hash of content referenced by the `media` field. Required if `media` is included.
  copies: number; // number of copies of this set of metadata in existence when token was minted.
  issued_at: number; // When token was issued or minted, Unix epoch in milliseconds
  expires_at: number; // When token expires, Unix epoch in milliseconds
  starts_at: number; // When token starts being valid, Unix epoch in milliseconds
  updated_at: number; // When token was last updated, Unix epoch in milliseconds
  extra: string; // anything extra the NFT wants to store on-chain. Can be stringified JSON.
  reference: string; // URL to an off-chain JSON file with more info.
  reference_hash: string; // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included.
}

@nearBindgen
export class Token {
  id: string;
  owner_id: string;
  metadata: TokenMetadata;
  constructor(token_id: string, metadata: TokenMetadata, receiver_id: string) {
    this.id = token_id;
    this.metadata = metadata;
    this.owner_id = receiver_id;
  }
}

@nearBindgen
export class ReitToken {
  token: Token;

  constructor(token_id: string, metadata: TokenMetadata, receiver_id: string) {
    this.token = { id: token_id, metadata: metadata, owner_id: receiver_id };
  }
  // --- view methods --- //

  nft_token(): Token {
    return this.token;
  }

  // --- change methods --- //

  nft_transfer(
    receiver_id: string,
    token_id: string,
    approval_id: number,
    memo: string
  ): void {
    // assert(false, 'nft_transfer not implemented');
  }

  nft_transfer_call(
    receiver_id: string,
    token_id: string,
    approval_id: number,
    memo: string,
    msg: string
  ): ContractPromise {
    // assert(false, 'nft_transfer_call not implemented');
    return ContractPromise.create('', '', {}, 1);
  }
}

四处询问后,我被指向两个不同的 GitHub 存储库,它们在 AssemblyScript 中实现了 NFT 代币智能合约。

在浏览了这些存储库之后,我注意到我的合约距离能够在钱包中显示我的 NFT 代币并不遥远。我不得不再实现一个功能,nft_metadata().

我的合同中确实有元数据,但作为变量,metadata。在 nft_metadata() 中返回相同的元数据似乎可以解决问题

@nearBindgen
class NFTContractMetadata {
  constructor(
    public spec: string = 'reit-token-0.0.0', // required, essentially a version like "nft-1.0.0"
    public name: string = 'Reit Token', // required, ex. "Mochi Rising — Digital Edition" or "Metaverse 3"
    public symbol: string = 'REIT', // required, ex. "MOCHI"
    public icon: string = '', // Data URL
    public base_uri: string = '', // Centralized gateway known to have reliable access to decentralized storage assets referenced by `reference` or `media` URLs
    public reference: string = '', // URL to a JSON file with more info
    public reference_hash: string = '' // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included.
  ) {}
}

@nearBindgen
export class Contract {
// ...

  nft_metadata(): NFTContractMetadata {
    return new NFTContractMetadata();
  }

// ...
}

我在测试时确实用一个新的 (transaction found here) 覆盖了我现有的 NFT,在这里,它在 NEAR testnet 钱包中可见