> 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("Player is not connected with 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 () {
  // create an instance of the web3 provider to interface with Metamask
  const provider = createEthereumProvider();
  // Create the object that will handle the sending and receiving of RPC messages
  const requestManager = new RequestManager(provider);
  // Check the current gas price on the Ethereum network
  const gasPrice = await requestManager.eth_gasPrice();
  // log response
  console.log({ gasPrice });
});
```

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

## 导入合约 ABI

ABI（Application Binary Interface，应用程序二进制接口）描述了如何与以太坊合约交互，确定有哪些可用函数、它们接受哪些输入以及输出什么内容。每个以太坊合约都有自己的 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 代币 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" ...等等`开头，请将其修改为以 `export default [{"constant":true,"inputs":[{"internalType":"bytes4" ...等等`.

### 实例化合约

导入 `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 () => {
  // create an instance of the web3 provider to interface with Metamask
  const provider = createEthereumProvider();
  // Create the object that will handle the sending and receiving of RPC messages
  const requestManager = new RequestManager(provider);
  // 基于 abi 创建一个工厂对象
  const factory = new ContractFactory(requestManager, abi);
  // 使用工厂对象实例化一个 `contract` 对象，引用特定合约
  const contract = (await factory.at(
    "0x2a8fd99c19271f4f04b1b7b9c4f7cf264b626edb"
  )) as any;
});
```

{% hint style="info" %}
**💡 提示**：对于遵循同一标准的合约，例如 ERC20 或 ERC721，你可以为所有合约导入一个通用 ABI。然后你可以生成一个 `ContractFactory` 对象，使用该 ABI，并用同一个工厂为每个合约实例化接口。
{% 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());
  }
});
```

上面的示例使用了一个 *fake MANA* 测试合约的 abi，并调用其 `setBalance` 方法向一个账户授予 100 *fake MANA* 。在改编此示例时，请将地址和 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" %}
**💡 提示**：将 position 参数更改为你场景的坐标，以便直接加载到你的场景中。。
{% endhint %}

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

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

当在旧版网页客户端中预览使用了以太坊库之一的场景时，你必须在单独的浏览器窗口中打开预览，在浏览器中打开 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
