> ## Documentation Index
> Fetch the complete documentation index at: https://docs.magicblock.gg/llms.txt
> Use this file to discover all available pages before exploring further.

# 定价

> MagicBlock 的定价模型借鉴了去中心化云基础设施。目标是在为开发者提供 **可预测计算成本** 的同时，也为需要优先访问或专属资源的企业提供 **灵活性**。

export const VRFCostSimulator = () => {
  const [vrfpm, setVrf] = useState(5);
  const [isER, setIsER] = useState(false);
  const alternativeVrfFeePerTx = 0.002;
  const magicblockVrfFeePerTx = 0.0005;
  const magicblockVrfFeePerTxDiscounted = 0.0;
  const solPriceUSD = 200;
  const days = Array.from({
    length: 30
  }, (_, i) => i + 1);
  const width = 600;
  const height = 300;
  const padding = 50;
  const minutesPerDay = 24 * 60;
  const alternativeVrfCosts = days.map((_, i) => (i + 1) * vrfpm * minutesPerDay * alternativeVrfFeePerTx * solPriceUSD);
  const magicblockVrfCosts = days.map((_, i) => {
    const feePerTx = isER ? magicblockVrfFeePerTxDiscounted : magicblockVrfFeePerTx;
    return (i + 1) * vrfpm * minutesPerDay * feePerTx * solPriceUSD;
  });
  const totalAlternativeVrfCost = vrfpm * minutesPerDay * days.length;
  const maxCost = Math.max(...alternativeVrfCosts, ...magicblockVrfCosts);
  const xStep = (width - padding * 2) / (days.length - 1);
  const yScale = val => height - padding - val / maxCost * (height - padding * 2);
  const linePath = data => data.map((val, i) => `${i === 0 ? "M" : "L"}${padding + i * xStep},${yScale(val)}`).join(" ");
  const lastIndex = days.length - 1;
  return <div style={{
    maxWidth: width
  }}>

            {}
      <div style={{
    marginBottom: "1rem",
    display: "flex",
    alignItems: "center",
    gap: "0.5rem"
  }}>
        <span style={{
    fontSize: "14px"
  }}>Solana</span>
        <label style={{
    position: "relative",
    display: "inline-block",
    width: "36px",
    height: "20px",
    marginBottom: 0,
    verticalAlign: "middle"
  }}>
          <input type="checkbox" checked={isER} onChange={() => setIsER(!isER)} style={{
    opacity: 0,
    width: 0,
    height: 0
  }} />
          {}
          <span style={{
    position: "absolute",
    cursor: "pointer",
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: isER ? "#2545f6" : "#2545f6",
    transition: ".4s",
    borderRadius: "24px"
  }} />

          {}
          <span style={{
    position: "absolute",
    height: "18px",
    width: "18px",
    left: isER ? "calc(100% - 19px)" : "1px",
    top: 1,
    bottom: "3px",
    backgroundColor: "white",
    transition: ".4s",
    borderRadius: "50%"
  }} />
        </label>
        <span style={{
    fontSize: "14px"
  }}>With ER</span>
      </div>

      {}
      <div style={{
    display: "flex",
    flexDirection: "column",
    gap: "1rem",
    marginTop: "1rem",
    marginBottom: "1rem"
  }}>
        {}
        <label style={{
    fontSize: "14px"
  }}>
          VRF request(s) per minute: {vrfpm.toLocaleString()}
          <input type="range" min="1" max="100" step="1" value={vrfpm} onChange={e => setVrf(Number(e.target.value))} style={{
    width: "100%"
  }} />
        </label>
      </div>

      {}
      <div style={{
    marginTop: "1rem",
    lineHeight: 1.5,
    fontSize: "14px"
  }}>
        <p>
          <strong>{(totalAlternativeVrfCost / 1_000_000).toLocaleString(undefined, {
    minimumFractionDigits: 0,
    maximumFractionDigits: 2
  })}M randomness provisions</strong> over 30 days.
            </p>

          <p style={{
    marginTop: "0.5rem"
  }}>
            {" "}You save{" "}
            <span style={{
    fontWeight: "bold",
    color: "#aa00ff"
  }}>
              ${(alternativeVrfCosts[lastIndex] - magicblockVrfCosts[lastIndex]).toLocaleString(undefined, {
    minimumFractionDigits: 0,
    maximumFractionDigits: 2
  })}{', or '}{(alternativeVrfCosts[lastIndex] / magicblockVrfCosts[lastIndex]).toLocaleString(undefined, {
    minimumFractionDigits: 0,
    maximumFractionDigits: 2
  })}x cheaper
            </span>
            .
          </p>

      </div>

      {}
      <div style={{
    width: "100%",
    maxWidth: "600px",
    margin: "0 auto",
    paddingLeft: "40px",
    paddingRight: "10px"
  }}>
        <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} width="100%" height="auto" preserveAspectRatio="xMidYMid meet" style={{
    overflow: "visible"
  }}>
          {Array.from({
    length: 5
  }, (_, i) => {
    const y = padding + i * ((height - 2 * padding) / 4);
    const price = ((4 - i) / 4 * maxCost).toFixed(0);
    return <g key={i}>
                <line x1={padding} y1={y} x2={width - padding} y2={y} stroke="#eee" />
                <text x={padding - 5} y={y + 4} textAnchor="end" fontSize="12" fill="#555" fontWeight="bold">
                  ${Number(price).toLocaleString()}
                </text>
              </g>;
  })}

          {days.map((day, i) => {
    if ((i + 1) % 10 === 0) {
      const x = padding + i * xStep;
      return <g key={i}>
                  <line x1={x} y1={padding} x2={x} y2={height - padding} stroke="#eee" />
                  <text x={x} y={height - padding + 15} textAnchor="middle" fontSize="12" fill="#555" fontWeight="bold">
                    {day}
                  </text>
                  <circle cx={x} cy={yScale(alternativeVrfCosts[i])} r={3} fill="#59e09d" />
                  <text x={x} y={yScale(alternativeVrfCosts[i]) - 8} fontSize="14" fill="#59e09d" textAnchor="middle" fontWeight="bold">
                    ${alternativeVrfCosts[i].toLocaleString()}
                  </text>
                  <circle cx={x} cy={yScale(magicblockVrfCosts[i])} r={3} fill="#aa00ff" />
                  <text x={x} y={yScale(magicblockVrfCosts[i]) - 8} fontSize="14" fill="#aa00ff" textAnchor="middle" fontWeight="bold">
                    ${magicblockVrfCosts[i].toLocaleString()}
                  </text>
                </g>;
    }
    return null;
  })}

          <line x1={padding} y1={padding} x2={padding} y2={height - padding} stroke="#aaa" />
          <line x1={padding} y1={height - padding} x2={width - padding} y2={height - padding} stroke="#aaa" />

          {}
          <text x={width / 2} y={height - padding + 40} fontSize="12" fill="#555" textAnchor="middle">
            Day
          </text>
          <path d={linePath(alternativeVrfCosts)} stroke="#59e09d" strokeWidth="2" fill="none" />
          <path d={linePath(magicblockVrfCosts)} stroke="#aa00ff" strokeWidth="2" fill="none" />
        </svg>
      </div>

      {}
      <div style={{
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
    flexWrap: "wrap",
    gap: "0.5rem",
    marginBottom: "1rem"
  }}>
        {}
        <div style={{
    display: "flex",
    gap: "0rem 1rem",
    flexWrap: "wrap"
  }}>
          <div style={{
    display: "flex",
    alignItems: "center",
    gap: "0.5rem"
  }}>
            <div style={{
    width: 12,
    height: 12,
    backgroundColor: "#59e09d"
  }} />
            <span style={{
    fontSize: "14px"
  }}>
              Other VRFs
            </span>
          </div>
          <div style={{
    display: "flex",
    alignItems: "center",
    gap: "0.5rem"
  }}>
            <div style={{
    width: 12,
    height: 12,
    backgroundColor: "#aa00ff"
  }} />
            <span style={{
    fontSize: "14px"
  }}>MagicBlock VRF</span>
          </div>
        </div>

        {}
        <div style={{
    display: "flex",
    alignItems: "center"
  }}>
          <span style={{
    fontSize: "14px"
  }}>Price: {solPriceUSD} USD/SOL</span>
        </div>
      </div>

    </div>;
};

export const ERCostSimulator = () => {
  const [tps, setTps] = useState(10000);
  const [cpm, setCpm] = useState(30);
  const [dpm, setDpm] = useState(1);
  const [isDedicated, setIsDedicated] = useState(false);
  const solanaFeePerTx = 0.000005;
  const erFeePerCommit = 0.0001;
  const erFeePerSession = 0.0003;
  const dedicatedBaseFee = 0.00000005;
  const solPriceUSD = 200;
  const days = Array.from({
    length: 30
  }, (_, i) => i + 1);
  const width = 600;
  const height = 300;
  const padding = 50;
  const secondsPerDay = 24 * 60 * 60;
  const commitFeesPerDay = cpm / 60 * secondsPerDay * erFeePerCommit * solPriceUSD;
  const sessionFeesPerDay = dpm / 60 * secondsPerDay * erFeePerSession * solPriceUSD;
  const solanaCosts = days.map((_, i) => (i + 1) * tps * secondsPerDay * solanaFeePerTx * solPriceUSD);
  const erCosts = days.map((_, i) => {
    const base = (i + 1) * (commitFeesPerDay + sessionFeesPerDay);
    const extra = isDedicated ? (i + 1) * tps * secondsPerDay * dedicatedBaseFee * solPriceUSD : 0;
    return base + extra;
  });
  const totalSolanaTx = tps * secondsPerDay * days.length;
  const maxCost = Math.max(...solanaCosts, ...erCosts);
  const xStep = (width - padding * 2) / (days.length - 1);
  const yScale = val => height - padding - val / maxCost * (height - padding * 2);
  const linePath = data => data.map((val, i) => `${i === 0 ? "M" : "L"}${padding + i * xStep},${yScale(val)}`).join(" ");
  const lastIndex = days.length - 1;
  const handleTpsChange = newTps => {
    setTps(newTps);
    const maxCpm = newTps * 20;
    if (cpm > maxCpm) {
      setCpm(maxCpm);
    }
    const maxDpm = newTps * 20;
    if (dpm > maxDpm) {
      setDpm(maxDpm);
    }
  };
  const handleCpmChange = newCpm => {
    const requiredTps = Math.ceil(newCpm / 2);
    if (requiredTps > tps) setTps(requiredTps);
    setCpm(newCpm);
  };
  const handleDpmChange = newDpm => {
    const requiredTps = Math.ceil(newDpm / 2);
    if (requiredTps > tps) setTps(requiredTps);
    setDpm(newDpm);
  };
  return <div style={{
    maxWidth: width
  }}>

      {}
      <div style={{
    marginBottom: "1rem",
    display: "flex",
    alignItems: "center",
    gap: "0.5rem"
  }}>
        <span style={{
    fontSize: "14px"
  }}>Public Node</span>
        <label style={{
    position: "relative",
    display: "inline-block",
    width: "36px",
    height: "20px",
    marginBottom: 0,
    verticalAlign: "middle"
  }}>
          <input type="checkbox" checked={isDedicated} onChange={() => setIsDedicated(!isDedicated)} style={{
    opacity: 0,
    width: 0,
    height: 0
  }} />
          {}
          <span style={{
    position: "absolute",
    cursor: "pointer",
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: isDedicated ? "#2545f6" : "#2545f6",
    transition: ".4s",
    borderRadius: "24px"
  }} />

          {}
          <span style={{
    position: "absolute",
    height: "18px",
    width: "18px",
    left: isDedicated ? "calc(100% - 19px)" : "1px",
    top: 1,
    bottom: "3px",
    backgroundColor: "white",
    transition: ".4s",
    borderRadius: "50%"
  }} />
        </label>
        <span style={{
    fontSize: "14px"
  }}>Dedicated Node</span>
      </div>

      {}
      <div style={{
    display: "flex",
    flexDirection: "column",
    gap: "1rem",
    marginTop: "1rem",
    marginBottom: "1rem"
  }}>
        {}
        <label style={{
    fontSize: "14px"
  }}>
          Transaction(s) per second: {tps.toLocaleString()}
          <input type="range" min="1" max="50000" step="1" value={tps} onChange={e => handleTpsChange(Number(e.target.value))} style={{
    width: "100%"
  }} />
        </label>

        {}
        <div style={{
    display: "flex",
    gap: "1rem"
  }}>
          <label style={{
    flex: 1,
    fontSize: "14px"
  }}>
            Commit(s) per minute: {cpm}
            <input type="range" min="1" max="100" step="1" value={cpm} onChange={e => handleCpmChange(Number(e.target.value))} style={{
    width: "100%"
  }} />
          </label>
          <label style={{
    flex: 1,
    fontSize: "14px"
  }}>
            Delegation Session(s) per minute: {dpm}
            <input type="range" min="1" max="100" step="1" value={dpm} onChange={e => handleDpmChange(Number(e.target.value))} style={{
    width: "100%"
  }} />
          </label>
        </div>
      </div>

      {}
      <div style={{
    marginTop: "1rem",
    lineHeight: 1.5,
    fontSize: "14px"
  }}>
        <p>
          <strong>{(totalSolanaTx / 1_000_000).toLocaleString(undefined, {
    minimumFractionDigits: 0,
    maximumFractionDigits: 2
  })}M transactions</strong> over 30 days.
            </p>

        {erCosts[lastIndex] < solanaCosts[lastIndex] ? <p style={{
    marginTop: "0.5rem"
  }}>
            {" "}You save{" "}
            <span style={{
    fontWeight: "bold",
    color: "#aa00ff"
  }}>
              ${(solanaCosts[lastIndex] - erCosts[lastIndex]).toLocaleString(undefined, {
    minimumFractionDigits: 0,
    maximumFractionDigits: 2
  })}{', or '}{(solanaCosts[lastIndex] / erCosts[lastIndex]).toLocaleString(undefined, {
    minimumFractionDigits: 0,
    maximumFractionDigits: 2
  })}x cheaper
            </span>
            .
          </p> : <p style={{
    marginTop: "0.5rem"
  }}>
            {" "}Try <strong>lowering commits and delegations</strong> to get a cost advantage.
          </p>}
      </div>

      {}
      <div style={{
    width: "100%",
    maxWidth: "600px",
    margin: "0 auto",
    paddingLeft: "40px",
    paddingRight: "10px"
  }}>
        <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} width="100%" height="auto" preserveAspectRatio="xMidYMid meet" style={{
    overflow: "visible"
  }}>
          {Array.from({
    length: 5
  }, (_, i) => {
    const y = padding + i * ((height - 2 * padding) / 4);
    const price = ((4 - i) / 4 * maxCost).toFixed(0);
    return <g key={i}>
                <line x1={padding} y1={y} x2={width - padding} y2={y} stroke="#eee" />
                <text x={padding - 5} y={y + 4} textAnchor="end" fontSize="12" fill="#555" fontWeight="bold">
                  ${Number(price).toLocaleString()}
                </text>
              </g>;
  })}

          {days.map((day, i) => {
    if ((i + 1) % 10 === 0) {
      const x = padding + i * xStep;
      return <g key={i}>
                  <line x1={x} y1={padding} x2={x} y2={height - padding} stroke="#eee" />
                  <text x={x} y={height - padding + 15} textAnchor="middle" fontSize="12" fill="#555" fontWeight="bold">
                    {day}
                  </text>
                  <circle cx={x} cy={yScale(solanaCosts[i])} r={3} fill="#59e09d" />
                  <text x={x} y={yScale(solanaCosts[i]) - 8} fontSize="14" fill="#59e09d" textAnchor="middle" fontWeight="bold">
                    ${solanaCosts[i].toLocaleString()}
                  </text>
                  <circle cx={x} cy={yScale(erCosts[i])} r={3} fill="#aa00ff" />
                  <text x={x} y={yScale(erCosts[i]) - 8} fontSize="14" fill="#aa00ff" textAnchor="middle" fontWeight="bold">
                    ${erCosts[i].toLocaleString()}
                  </text>
                </g>;
    }
    return null;
  })}

          <line x1={padding} y1={padding} x2={padding} y2={height - padding} stroke="#aaa" />
          <line x1={padding} y1={height - padding} x2={width - padding} y2={height - padding} stroke="#aaa" />

          {}
          <text x={width / 2} y={height - padding + 40} fontSize="12" fill="#555" textAnchor="middle">
            Day
          </text>
          <path d={linePath(solanaCosts)} stroke="#59e09d" strokeWidth="2" fill="none" />
          <path d={linePath(erCosts)} stroke="#aa00ff" strokeWidth="2" fill="none" />
        </svg>
      </div>

      {}
      <div style={{
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
    flexWrap: "wrap",
    gap: "0.5rem",
    marginBottom: "1rem"
  }}>
        {}
        <div style={{
    display: "flex",
    gap: "0rem 1rem",
    flexWrap: "wrap"
  }}>
          <div style={{
    display: "flex",
    alignItems: "center",
    gap: "0.5rem"
  }}>
            <div style={{
    width: 12,
    height: 12,
    backgroundColor: "#59e09d"
  }} />
            <span style={{
    fontSize: "14px"
  }}>Solana Only</span>
          </div>
          <div style={{
    display: "flex",
    alignItems: "center",
    gap: "0.5rem"
  }}>
            <div style={{
    width: 12,
    height: 12,
    backgroundColor: "#aa00ff"
  }} />
            <span style={{
    fontSize: "14px"
  }}>MagicBlock (ER Sessions + Commits)</span>
          </div>
        </div>

        {}
        <div style={{
    display: "flex",
    alignItems: "center"
  }}>
          <span style={{
    fontSize: "14px"
  }}>Price: {solPriceUSD} USD/SOL</span>
        </div>
      </div>

    </div>;
};

***

## 产品定价

<div id="ephemeral-rollup" />

<Tabs>
  <Tab title="Ephemeral Rollup">
    **Public nodes** 让你可以以零摩擦、免费交易的方式开始在 MagicBlock 上构建。只有在关闭会话或将数据提交回 Solana 时才会产生费用。

    <table style={{ width: "100%", tableLayout: "fixed" }}>
      <thead>
        <tr>
          <th>费用类型</th>
          <th>金额 (SOL)</th>
          <th>说明</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>基础费用</td>
          <td>0</td>
          <td>每笔交易 (Tx)</td>
        </tr>

        <tr>
          <td>会话费用</td>
          <td>0.0003</td>
          <td>每个 ER 会话（在 undelegation 时收取）</td>
        </tr>

        <tr>
          <td>提交费用</td>
          <td>0.0001</td>
          <td>每次提交到 Solana</td>
        </tr>
      </tbody>
    </table>

    **Dedicated nodes** 适合企业和大规模团队。借助专属基础设施，你可以获得更高可靠性、可预测成本以及 MEV 保护。

    [了解更多 ER →](/cn/pages/ephemeral-rollups-ers/how-to-guide/quickstart)

    ### ER 成本模拟器：30 天

    <ERCostSimulator />
  </Tab>

  <Tab title="Private Ephemeral Rollup">
    Private Ephemeral Rollup 支持由智能合约定义的自定义私密计算。

    自定义 PER 逻辑使用标准 ER 定价。[查看 Ephemeral Rollup 定价 →](#ephemeral-rollup)
  </Tab>

  <Tab title="VRF">
    VRF 服务提供 **链上可证明公平的随机性**。费用涵盖证明生成与上链发布。

    > ⚠️ 注意：这些成本不包含请求随机性的交易本身。在 ER 上交易免费，在 Solana 上则可能因你的 priority fee 设置而不同。

    <table style={{ width: "100%", tableLayout: "fixed" }}>
      <thead>
        <tr>
          <th>VRF 类型</th>
          <th>金额 (SOL)</th>
          <th>说明</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>ER (\<50 ms)</td>
          <td>免费</td>
          <td>每次随机性请求</td>
        </tr>

        <tr>
          <td>Solana (\<500 ms)</td>
          <td>0.0008</td>
          <td>每次随机性请求</td>
        </tr>

        <tr>
          <td>Solana (1/2 seconds)</td>
          <td>0.0005</td>
          <td>每次随机性请求</td>
        </tr>
      </tbody>
    </table>

    ### VRF 成本模拟器：30 天

    <VRFCostSimulator />

    [了解更多 Solana VRF →](/cn/pages/verifiable-randomness-functions-vrfs/introduction/solana-vrf)
  </Tab>

  <Tab title="Private Payments API">
    Private Payment API 让你能够轻松在 Solana Mainnet 和/或 Private ER 上发送私密稳定币转账。

    <table style={{ width: "100%", tableLayout: "fixed" }}>
      <thead>
        <tr>
          <th>支付类型</th>
          <th>固定费用 (SOL)</th>
          <th>按量收费</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>Solana Mainnet</td>
          <td>0.002</td>
          <td>0.1%</td>
        </tr>
      </tbody>
    </table>

    <CardGroup cols={1}>
      <Card title="API 参考" icon="book" href="/cn/pages/private-ephemeral-rollups-pers/api-reference/per/introduction" iconType="duotone">
        浏览 Private Payments API 的各个端点
      </Card>
    </CardGroup>
  </Tab>
</Tabs>

***

## 客户支持

如果你需要 **自建节点** 相关支持，请联系：

📧 [development@magicblock.xyz](mailto:development@magicblock.xyz)

<CardGroup cols={2}>
  <Card title="Ephemeral Rollup（ER）" icon="bolt" href="/cn/pages/ephemeral-rollups-ers/how-to-guide/quickstart" iconType="duotone">
    在 Solana 上安全执行实时、零手续费交易。
  </Card>

  <Card title="Private Ephemeral Rollup（PER）" icon="shield-check" href="/cn/pages/private-ephemeral-rollups-pers/how-to-guide/quickstart" iconType="duotone">
    在合规的前提下保护敏感数据——基于 Ephemeral Rollups 构建。
  </Card>

  <Card title="私密支付 API" icon="bag-shopping-plus" href="/cn/pages/private-ephemeral-rollups-pers/api-reference/per/introduction" iconType="duotone">
    几秒钟为你的应用集成链上私密转账——默认合规。
  </Card>

  <Card title="Solana VRF" icon="dice" href="/cn/pages/verifiable-randomness-functions-vrfs/introduction/solana-vrf" iconType="duotone">
    为游戏、抽奖和实时应用添加可证明公平的链上随机数。
  </Card>

  <Card title="价格预言机" icon="waveform" href="/cn/pages/tools/oracle/introduction" iconType="duotone">
    获取适用于交易和 DeFi 的低延迟链上价格数据。
  </Card>
</CardGroup>
