mcpField
N
nft-blockchain

nft-blockchain

github.com/dcl-regenesislabs开发1741 次安装21 周前更新
代码仓库

关于 nft-blockchain

nft-blockchain 是面向 Decentraland 开发的 NFT 与 Ethereum 区块链参考资料,介绍 NFT 展示及链上功能。内容涵盖钱包检查、签名请求、智能合约、RPC 调用和 Sepolia 测试。

主要功能

  1. 01展示 ERC-721 NFT 艺术品
  2. 02检查玩家钱包及访客状态
  3. 03发送钱包签名的后端请求
  4. 04使用 eth-connect 与合约交互
  5. 05发起自定义 Ethereum RPC 调用
  6. 06在 Sepolia 上测试合约

适用场景

  1. 01在场景中添加带框 NFT 艺术品
  2. 02检查玩家是否能签署交易
  3. 03用钱包签名验证后端请求
  4. 04开发和测试智能合约交互

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dcl-regenesislabs/opendcl --skill nft-blockchain

安装后在 Claude Code 中输入/nft-blockchain确认已加载。

详细介绍

Decentraland 中的 NFT 和区块链

显示 NFT 艺术品

NftShape 已在 main-entities.ts 中受支持——可直接声明带边框的 NFT。用户可以在可视化编辑器中拖动它。

// main-entities.ts
import type { Scene } from '@dcl/sdk/scene-types'

export const scene = {
  hero_nft: {
    components: {
      Transform: { position: { x: 8, y: 2, z: 8 } },
      NftShape: {
        urn: 'urn:decentraland:ethereum:erc721:0x06012c8cf97bead5deae237070f9587f8e7a266d:558536',
        color: { r: 1, g: 1, b: 1, a: 1 },
        style: 0  // NftFrameType.NFT_CLASSIC — enum values are integers in the literal
      }
    }
  }
} satisfies Scene

style 字段是一个数值枚举——不能直接在字面量中引用 NftFrameType.NFT_CLASSIC,因为 AST 遍历器只接受兼容 JSON 的表达式。请使用整数值(见下表),并添加注释。

NFT URN 格式
urn:decentraland:ethereum:erc721:<contractAddress>:<tokenId>
  • 适用于 Ethereum 主网中的任何 ERC-721 NFT
  • 系统会自动从 NFT 的元数据中加载图片
可用的边框样式
valueenum namedescription
0NFT_CLASSIC简约经典边框
1NFT_BAROQUE_ORNAMENT华丽的巴洛克风格
2NFT_DIAMOND_ORNAMENT菱形图案
3NFT_MINIMAL_WIDE简约宽边框
4NFT_MINIMAL_GREY简约灰色边框
5NFT_BLOCKY像素化/方块风格
6NFT_GOLD_EDGES金色边缘装饰
7NFT_GOLD_CARVED雕刻金色边框
8NFT_GOLD_WIDE宽金色边框
9NFT_GOLD_ROUNDED圆角金色边框
10NFT_METAL_MEDIUM中等金属质感
11NFT_METAL_WIDE宽金属边框
12NFT_METAL_SLIM窄金属边框
13NFT_METAL_ROUNDED圆角金属边框
14NFT_PINS用图钉固定在墙上
15NFT_MINIMAL_BLACK简约黑色边框
16NFT_MINIMAL_WHITE简约白色边框
17NFT_TAPE用胶带贴在墙上
18NFT_WOOD_SLIM窄木质边框
19NFT_WOOD_WIDE宽木质边框
20NFT_WOOD_TWIGS树枝/枝条木质边框
21NFT_CANVAS画布风格
22NFT_NONE无边框

在允许使用枚举标识符的 src/index.ts 中,可直接使用 NftFrameType.NFT_CLASSIC 等标识符。

检查玩家钱包

import { getPlayer } from '@dcl/sdk/src/players'

function checkWallet() {
  const player = getPlayer()
  if (player && !player.isGuest) {
    console.log('Player wallet address:', player.userId)
    // userId is the Ethereum wallet address
  } else {
    console.log('Player is guest (no wallet)')
  }
}

尝试进行任何区块链交互之前,务必先检查 isGuest——访客玩家没有连接的钱包。

签名请求

向后端发送使用玩家钱包签名的经过身份验证的请求:

import { signedFetch } from '~system/SignedFetch'

executeTask(async () => {
  try {
    const response = await signedFetch({
      url: 'https://example.com/api/action',
      init: {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          action: 'claimReward',
          amount: 100
        })
      }
    })

    if (!response.ok) {
      console.error('HTTP error:', response.status)
      return
    }
    const result = JSON.parse(response.body)
    console.log('Result:', result)
  } catch (error) {
    console.log('Request failed:', error)
  }
})

signedFetch 会自动附加用于证明玩家身份的加密签名。后端可以验证此签名,以验证请求身份。

智能合约交互

需要安装 eth-connect 包:

npm install eth-connect
将 ABI 存储在单独的文件中
// contracts/myContract.ts
export default [
  {
    "constant": true,
    "inputs": [{ "name": "_owner", "type": "address" }],
    "name": "balanceOf",
    "outputs": [{ "name": "balance", "type": "uint256" }],
    "type": "function"
  }
  // ... rest of ABI
]
创建合约实例
import { RequestManager, ContractFactory } from 'eth-connect'
import { createEthereumProvider } from '@dcl/sdk/ethereum-provider'
import { abi } from '../contracts/myContract'

executeTask(async () => {
  try {
    // Create web3 provider
    const provider = createEthereumProvider()
    const requestManager = new RequestManager(provider)

    // Create contract at a specific address
    const factory = new ContractFactory(requestManager, abi)
    const contract = await factory.at('0x2a8fd99c19271f4f04b1b7b9c4f7cf264b626edb') as any

    // Read data (no gas required)
    const balance = await contract.balanceOf('0x123...abc')
    console.log('Balance:', balance)
  } catch (error) {
    console.log('Contract interaction failed:', error)
  }
})
写入操作(需要 Gas)
executeTask(async () => {
  try {
    const userData = getPlayer()
    if (userData.isGuest) return

    // Write operation — prompts the player to sign the transaction
    const writeResult = await contract.transfer(
      '0xRecipientAddress',
      100,
      {
        from: userData.userId,
        gas: 100000,
        gasPrice: await requestManager.eth_gasPrice()
      }
    )
    console.log('Transaction hash:', writeResult)
  } catch (error) {
    console.log('Transaction failed:', error)
  }
})
Gas 价格和余额检查
import { RequestManager } from 'eth-connect'
import { createEthereumProvider } from '@dcl/sdk/ethereum-provider'

executeTask(async () => {
  const provider = createEthereumProvider()
  const requestManager = new RequestManager(provider)

  const gasPrice = await requestManager.eth_gasPrice()
  console.log('Current gas price:', gasPrice)

  const balance = await requestManager.eth_getBalance('0x123...abc', 'latest')
  console.log('Account balance:', balance)
})

使用 Sepolia 测试

开发时,请使用 Sepolia 测试网:

  1. 将 MetaMask 设置为 Sepolia 网络
  2. 从 Sepolia 水龙头获取测试 ETH
  3. 将合约部署到 Sepolia
  4. 主网和测试网的合约地址不同——请使用环境检查
自定义 RPC 调用

对于 eth-connect 辅助工具未涵盖的底层 Ethereum RPC 调用,请使用 sendAsync:

import { sendAsync } from '~system/EthereumController'

const result = await sendAsync({ method: 'eth_blockNumber', params: [] })
console.log('Current block:', result.body)
打开 URL 和 NFT 对话框

使用受限操作打开外部链接和 NFT 详情视图:

import { openExternalUrl, openNftDialog } from '~system/RestrictedActions'

openExternalUrl({ url: 'https://opensea.io/collection/...' })
openNftDialog({ urn: 'urn:decentraland:ethereum:erc721:0x06012c8cf97BEaD5deAe237070F9587f8E7A266d:558536' })

最佳实践

  • 任何区块链交互之前,务必检查 isGuest——访客玩家无法签署交易
  • 所有异步区块链调用都使用 executeTask(async () => { ... })
  • 将 ABI 文件单独存储(例如放在 contracts/ 中)——不要内联大型 ABI
  • 妥善处理错误——区块链操作可能失败(用户拒绝、Gas 不足、网络问题)
  • 必须将 eth-connect 安装为依赖项:npm install eth-connect
  • 使用 signedFetch 进行后端身份验证,而非原始的 fetch——它可以证明玩家身份
  • 读取操作(view/pure 函数)不需要 Gas;写入操作会提示用户签名
  • 部署到主网之前,先在 Sepolia 上测试
  • NFT URN 仅适用于 Ethereum 主网的 ERC-721 代币

评论

支持 Markdown