本节作者：[@LiKang](https://x.com/banlideli)

这一讲将会介绍如何实现通过区块链转账和收款。

---

## 转账

在区块链环境中，转账是指在参与者之间转移资产的行为，这些资产可以是加密货币（如比特币、以太坊等）或者其他基于区块链的数字资产（如代币、NFTs 等）。这些转账活动被记录在区块链上，并受到网络共识机制的安全保护。转账是最基础的区块链网络操作，它涉及以下几个要点：

`源地址（发送方）` ： 需要转出资产的区块链账户地址。

`目标地址（接收方）` ： 将接收资产的区块链账户地址。

`资产数量` ： 想要转账的资产的确切数量或价值。

`交易费用` ： 通常由执行交易的矿工或验证节点收取的费用。费用的多少可以影响交易的确认速度。

`网络` ： 完成转账的区块链网络（例如比特币网络、以太坊网络）。

转账发生后，它必须被网络中的矿工或其他共识机制参与者确认，并记录在一个区块中，最终被添加到区块链上。

区块链转账的过程大致包括以下步骤：

1. 发起方用其私钥对转账信息进行签名，并将这些信息广播到网络。

2. 网络中的节点（矿工或验证者）接收到交易请求，并验证签名和交易的有效性。

3. 一旦验证无误，转账会被打包到其他交易中构成一个新的区块。

4. 这个区块经过网络共识机制的确认后，被添加到区块链上。

5. 交易完成后，目标地址上的资产余额更新，体现了转账的结果。

这个转账过程的确切细节可能会根据所使用的具体区块链技术和资产类型而有所不同。

### 发起一个转账

我们先来实现前端部分逻辑，我们基于之前的课程先快速实现[连接钱包](../03_ConnectWallet/readme.md)。

新建一个 `pages/transaction/index.tsx` 文件，复制之前的代码，然后做下修改，新建一个 `pages/transaction/SendEth.tsx` 的组件：

```diff
  import React from "react";
  import { MetaMask, WagmiWeb3ConfigProvider} from "@ant-design/web3-wagmi";
  import { createConfig, http } from "wagmi";
  import { injected } from "wagmi/connectors";
  import { mainnet, sepolia } from "wagmi/chains";
  import { ConnectButton, Connector } from '@ant-design/web3';
+ import { SendEth } from "../../components/SendEth";


  const config = createConfig({
    chains: [mainnet, sepolia],
    transports: {
      [mainnet.id]: http(),
      [sepolia.id]: http(),
    },
    connectors: [
      injected({
        target: "metaMask",
      }),
    ],
  });
  const TransactionDemo: React.FC = () => {

    return (
      <WagmiWeb3ConfigProvider
        config={config}
        eip6963={{
          autoAddInjectedWallets: true,
        }}
        wallets={[MetaMask()]}
      >
        <Connector>
          <ConnectButton />
        </Connector>
+       <SendEth />
      </WagmiWeb3ConfigProvider>
    );
  };
  export default TransactionDemo;

```

然后在 `SendEth` 组件内写一个输入 `to` 和 `value` 的输入框并发起一个转账的按钮，代码如下：

```tsx
import * as React from "react";
import { Button, Checkbox, Form, type FormProps, Input } from "antd";
import {
  type BaseError,
  useSendTransaction,
  useWaitForTransactionReceipt,
} from "wagmi";
import { parseEther } from "viem";

type FieldType = {
  to: `0x${string}`;
  value: string;
};

export const SendEth: React.FC = () => {
  const {
    data: hash,
    error,
    isPending,
    sendTransaction,
  } = useSendTransaction();

  const { isLoading: isConfirming, isSuccess: isConfirmed } =
    useWaitForTransactionReceipt({ hash });

  const onFinish: FormProps<FieldType>["onFinish"] = (values) => {
    console.log("Success:", values);
    sendTransaction({ to: values.to, value: parseEther(values.value) });
  };

  const onFinishFailed: FormProps<FieldType>["onFinishFailed"] = (
    errorInfo
  ) => {
    console.log("Failed:", errorInfo);
  };

  return (
    <Form
      name="basic"
      labelCol={{ span: 8 }}
      wrapperCol={{ span: 16 }}
      style={{ maxWidth: 600 }}
      initialValues={{ remember: true }}
      onFinish={onFinish}
      onFinishFailed={onFinishFailed}
      autoComplete="off"
    >
      <Form.Item<FieldType>
        label="to"
        name="to"
        rules={[{ required: true, message: "Please input!" }]}
      >
        <Input />
      </Form.Item>

      <Form.Item<FieldType>
        label="value"
        name="value"
        rules={[{ required: true, message: "Please input!" }]}
      >
        <Input />
      </Form.Item>

      <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
        <Button type="primary" htmlType="submit">
          {isPending ? "Confirming..." : "Send"}
        </Button>
      </Form.Item>

      {hash && <div>Transaction Hash: {hash}</div>}
      {isConfirming && <div>Waiting for confirmation...</div>}
      {isConfirmed && <div>Transaction confirmed.</div>}
      {error && (
        <div>Error: {(error as BaseError).shortMessage || error.message}</div>
      )}
    </Form>
  );
};
```

代码里，我们用了 [Ant Design](https://ant.design/components/form) 的 `Form` 组件 和 `wagmi` 的 `hooks` ，发起了一个交易，并进行了状态的监听，输入 `to` 和 `value` 点击发起会出现如下图的效果：

![发起](./img/send.png)

至此，我们完成了一个简单的转账需求的实现。你可以访问 [https://wtf-dapp.vercel.app/transaction](https://wtf-dapp.vercel.app/transaction) 体验完整的 Demo。为了避免你的资金损失，请谨慎操作。

## 收款

在区块链上收款通常意味着接收加密货币或其他基于区块链的资产，如代币（包括 NFTs）。把你的公共地址提供给付款方。你可以直接提供地址字符串或者生成一个二维码，方便手机钱包扫码。

值得我们注意的是：

1. 不要共享你的私钥或助记词。只有你应该有这些信息。
2. 确保你提供的地址是完全准确的。地址如果有误，资金可能会丢失。
3. 付款方需要支付一定的网络费用（或者“矿工费”），这直接影响交易的处理速度。
4. 区块链交易一旦开始就无法取消，只能等待他们被网络确认。
5. 请确保使用正确的区块链网络。比如，只能向以太坊网络的地址发送以太币（ETH），向比特币网络的地址发送比特币（BTC）。

### 二维码收款

`ant-design-web3` 提供了一个收款的快捷组件，只需要传入选择链，选择钱包，输入金额就可以支持指定钱包的快捷扫码付款啦。

你可以在这里找到文档：[PayPanel - Ant Design Web3](https://web3.ant.design/components/pay-panel)
