> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-zh/chang-jing-sdk7/qu-kuai-lian/scene-blockchain-operations.md).

# 场景区块链操作

了解 SDK 提供了哪些用于执行以太坊区块链操作的功能

Decentraland 场景可以与以太坊区块链交互。这可用于获取用户钱包及其中代币的数据，或触发可能涉及任何以太坊代币（同质化或非同质化）的交易。这有很多用途，例如出售代币、在游戏机制中将代币作为奖励、根据玩家是否拥有某些代币来改变其与场景的交互方式等。

请注意，场景触发的以太坊主网中的所有交易都需要玩家确认并支付 gas 费用。

所有区块链操作也需要以 [异步函数](/creator/content-creator-zh/chang-jing-sdk7/bian-cheng-mo-shi/async-functions.md)的形式执行，因为其时序取决于外部事件。

## 获取玩家的以太坊账户

要获取玩家的以太坊账户，请使用 `getPlayer()` 函数。

```ts
import { getPlayer } from "@dcl/sdk/src/players";

export function main() {
  let userData = getPlayer();
  if (!userData) return;
  if (!userData.isGuest) {
    console.log(userData.userId);
  } else {
    console.log("玩家未连接到 Web3");
  }
}
```

请注意，如果玩家以访客身份进入 Decentraland，则不会有已连接的以太坊钱包。如果他们是以访客身份连接的， `isGuest` 字段在 `getPlayer()` 的返回结果中将为 true。否则，你可以从 `userId` 字段获取玩家的钱包地址。要了解更多可从玩家那里获取的数据，请参阅 [获取玩家数据](/creator/content-creator-zh/chang-jing-sdk7/jiao-hu-xing/user-data.md#get-player-data)

{% hint style="warning" %}
**📔 注意**：尽管 eth 地址可能包含大写字符，但某些浏览器会自动将返回的字符串转换为小写。如果你希望比较地址值并确保在所有浏览器上都能正常工作，请使用 `.toLowerCase()` 方法将值转换为小写。
{% endhint %}

## 检查 gas 价格

导入 `eth-connect` 库后，你必须实例化一个 web3 provider 和一个 request manager，这将允许你通过 web3 连接到玩家浏览器中的 Metamask。

下面的函数会获取以太坊主网当前的 gas 价格并将其打印出来。

```ts
import { RequestManager } from "eth-connect";
import { createEthereumProvider } from "@dcl/sdk/ethereum-provider";

executeTask(async function () {
  // 创建一个 web3 provider 实例以与 Metamask 交互
  const provider = createEthereumProvider();
  // 创建一个用于处理 RPC 消息发送与接收的对象
  const requestManager = new RequestManager(provider);
  // 检查以太坊网络当前的 gas 价格
  const gasPrice = await requestManager.eth_gasPrice();
  // 输出响应
  console.log({ gasPrice });
});
```

{% hint style="info" %}
**💡 提示**：请注意，由 `requestManager` 处理的函数必须使用 `await`调用，因为它们依赖于获取外部数据，完成可能需要一些时间。
{% endhint %}

## 导入合约 ABI

ABI（应用二进制接口）描述了如何与以太坊合约交互，决定了可用的函数、它们接受哪些输入以及输出什么。每个以太坊合约都有自己的 ABI，你应该导入项目中希望使用的所有合约的 ABI。

例如，下面是 MANA ABI 中一个函数的示例：

```ts
{
  anonymous: false,
  inputs: [
    {
      indexed: true,
      name: 'burner',
      type: 'address'
    },
    {
      indexed: false,
      name: 'value',
      type: 'uint256'
    }
  ],
  name: 'Burn',
  type: 'event'
}
```

ABI 定义可能相当冗长，因为它们通常包含很多函数，因此我们建议将 ABI 文件的 JSON 内容粘贴到一个单独的 `.ts` 文件中，并从那里将其导入到其他场景文件中。我们还建议将所有 ABI 文件保存在场景中的一个单独文件夹里，命名为 `/contracts`.

```ts
import { abi } from "../contracts/mana";
```

这里有不同 Decentraland 合约的链接。通过点击 *Export ABI* 并选择 *JSON Format*.

* [MANA Token ABI](https://etherscan.io/address/0x0f5d2fb29fb7d3cfee444a200298f468908cc942#code)
* [Decentraland Marketplace](https://etherscan.io/address/0x19a8ed4860007a66805782ed7e0bed4e44fc6717#code)
* [LAND ABI](https://etherscan.io/address/0xf87e31492faf9a91b02ee0deaad50d51d56d5d4d#code)
* [Estate ABI](https://etherscan.io/address/0x959e104e1a4db6317fa58f8295f586e1a978c297#code)
* [AvatarNameRegistry ABI](https://etherscan.io/address/0x894b883905bfEe2CC448880F1b59f4A762E67566)
* [Catalyst ABI](https://etherscan.io/address/0xcc054fab08127c19f621ab83ade5962cd10584ec)

以下是各种可穿戴收藏系列的合约：（每个收藏系列都是作为独立合约发行的）

* [ExclusiveMasksCollection ABI](https://etherscan.io/address/0xc04528c14c8ffd84c7c1fb6719b4a89853035cdd)
* [Halloween2019Collection ABI](https://etherscan.io/address/0xc1f4b0eea2bd6690930e6c66efd3e197d620b9c2)
* [Halloween2019CollectionFactory ABI](https://etherscan.io/address/0x07ccfd0fbada4ac3c22ecd38037ca5e5c0ad8cfa)
* [Xmas2019Collection ABI](https://etherscan.io/address/0xc3af02c0fd486c8e9da5788b915d6fff3f049866)
* [MCHCollection ABI](https://etherscan.io/address/0xf64dc33a192e056bb5f0e5049356a0498b502d50)
* [CommunityContestCollection ABI](https://etherscan.io/address/0x32b7495895264ac9d0b12d32afd435453458b1c6)
* [DCLLaunchCollection ABI](https://etherscan.io/address/0xd35147be6401dcb20811f2104c33de8e97ed6818)
* [DCGCollection ABI](https://etherscan.io/address/0x3163d2cfee3183f9874e2869942cc62649eeb004)

{% hint style="info" %}
**💡 提示**：要清楚地查看合约暴露的函数，请在 [abitopic.io](https://abitopic.io)中打开它。只需将合约地址粘贴到那里，然后打开 *functions* 选项卡即可查看支持的函数及其参数完整列表。你甚至可以通过网页使用不同参数测试调用这些函数。
{% endhint %}

要让 TypeScript 能够从 JSON 文件中导入并不容易。更简单的推荐变通方法是将 `ABI.JSON` 文件扩展名改为 `.ts` 并稍作修改，使其内容以 `export default`.

开头。例如，如果 ABI 文件内容以 `[{"constant":true,"inputs":[{"internalType":"bytes4" ...etc`开头，则将其修改为以 `export default [{"constant":true,"inputs":[{"internalType":"bytes4" ...etc`.

### 实例化合约

导入 `eth-connect` 库以及合约的 *abi*后，你必须实例化几个对象，这些对象将允许你使用合约中的函数，并连接到玩家浏览器中的 Metamask。

你还必须导入 web3 provider。这是因为玩家浏览器中的 Metamask 使用 web3，所以我们需要一种与之交互的方式。

```ts
import { RequestManager, ContractFactory } from "eth-connect";
import { createEthereumProvider } from "@dcl/sdk/ethereum-provider";
import { abi } from "../contracts/mana";

executeTask(async () => {
  // 创建一个 web3 provider 实例以与 Metamask 交互
  const provider = createEthereumProvider();
  // 创建一个用于处理 RPC 消息发送与接收的对象
  const requestManager = new RequestManager(provider);
  // 基于 abi 创建一个 factory 对象
  const factory = new ContractFactory(requestManager, abi);
  // 使用 factory 对象实例化一个 `contract` 对象，引用某个特定合约
  const contract = (await factory.at(
    "0x2a8fd99c19271f4f04b1b7b9c4f7cf264b626edb"
  )) as any;
});
```

{% hint style="info" %}
**💡 提示**：对于遵循相同标准的合约，例如 ERC20 或 ERC721，你可以为所有合约导入一个通用 ABI。然后你生成一个 `ContractFactory` 对象，使用该 ABI，并用同一个 factory 为每个合约实例化接口。
{% endhint %}

### 调用合约中的方法

一旦你创建了 `contract` 对象，就可以轻松调用其 ABI 中定义的函数，并传入指定的输入参数。

```ts
import { getPlayer } from "@dcl/sdk/src/players";
import { createEthereumProvider } from "@dcl/sdk/ethereum-provider";
import { RequestManager, ContractFactory } from "eth-connect";
import { abi } from "../contracts/mana";

executeTask(async () => {
  try {
    // 上文部分中解释的设置步骤
    const provider = createEthereumProvider();
    const requestManager = new RequestManager(provider);
    const factory = new ContractFactory(requestManager, abi);
    const contract = (await factory.at(
      "0x2a8fd99c19271f4f04b1b7b9c4f7cf264b626edb"
    )) as any;
    let userData = getPlayer();
    if (!userData || userData.isGuest) {
      return;
    }

    // 执行合约中的一个函数
    const res = await contract.setBalance(
      "0xaFA48Fad27C7cAB28dC6E970E4BFda7F7c8D60Fb",
      100,
      {
        from: userData.userId,
      }
    );
    // 输出响应
    console.log(res);
  } catch (error: any) {
    console.log(error.toString());
  }
});
```

上面的示例使用了一个 *假的 MANA* 测试合约的 abi，并调用其 `setBalance` 方法向某个账户授予 100 *假的 MANA* 。在改编此示例时，请将地址和 abi 替换为你要调用的合约的地址和 abi，并调用其 abi 所定义的方法。

### 其他函数

eth-connect 库还包含许多你可以使用的其他辅助函数。例如用于：

* 获取估算的 gas 价格
* 获取给定地址的余额
* 获取交易回执
* 获取从某个地址发送的交易数量
* 在多种格式之间转换，包括十六进制、二进制、utf8 等。

## 使用以太坊测试网络

在测试场景时，为了避免转移真实的 MANA 或其他货币，你可以使用 *以太坊 Sepolia 测试网络* 并改为转移假的测试网 MANA。

要使用测试网络，你必须将 Metamask Chrome 扩展设置为使用 *Sepolia 测试网络* 而不是 *主网络*.

你需要获取 Sepolia Ether，你可以从各种外部水龙头免费获得，例如 [这个](https://www.alchemy.com/faucets/ethereum-sepolia/).

{% hint style="info" %}
**💡 提示**：要执行将 Sepolia MANA 转入你的钱包的交易，你需要以 Sepolia Ether 支付 gas 费。
{% endhint %}

要使用测试网络预览你的场景，请将以下 URL 粘贴到浏览器标签页中。这将在 Decentraland 桌面客户端中打开该场景：

`decentraland://realm=http://127.0.0.1:8000&local-scene=true&debug=true&dclenv=zone&position=0,0`

{% hint style="info" %}
**💡 提示**：将位置参数更改为你场景的坐标，以便直接加载到你的场景中..
{% endhint %}

在此模式下浏览场景时，你接受的任何交易都只会发生在测试网络中，不会影响你真实钱包中的 MANA 余额。

如果你需要在 Polygon 测试网中测试交易，并且需要在该测试网上拥有 MANA，那么在 Sepolia 上获取后，你需要将 MANA 兑换到该网络。要将 Sepolia MANA 跨链到 Polygon 测试网，请访问你的 [Sepolia 中的 Decentraland 账户页面](https://account.decentraland.zone/) 并在以太坊 MANA 一侧点击“swap”。

当在旧版 Web 客户端上运行使用其中一个以太坊库的场景预览时，你必须在单独的浏览器窗口中打开预览，在浏览器中打开 Metamask，并手动添加字符串 `&ENABLE_WEB3`.

## 发送自定义 RPC 消息

使用函数 `sendAsync()` 通过 [RPC 协议](https://en.wikipedia.org/wiki/Remote_procedure_call).

```ts
import { sendAsync } from "~system/EthereumController";

// 发送一条消息
await sendAsync({
  id: 1,
  method: "myMethod",
  jsonParams: "{ myParam: myValue }",
});
```

## Decentraland 智能合约

在下面的链接中，你可以找到与 Decentraland 生态系统相关的一系列以太坊智能合约。该列表包括主网以及其他以太坊测试网络上的合约。

[contracts.decentraland.org](https://contracts.decentraland.org/links)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.decentraland.org/creator/content-creator-zh/chang-jing-sdk7/qu-kuai-lian/scene-blockchain-operations.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
