# ガス代行支払い

ほとんどのブロックチェーンシステムでは、すべてのトランザクションにおいて、開始者が「ガス」として一般的に知られる手数料を支払う必要があります。これは、これらの手数料を支払うためのネイティブ通貨を持っていない可能性のある新規ユーザーにとって、大きな障壁となり得ます。OCAP Clientは、アプリケーション開発者がこれらの手数料を負担できるようにするガス代行支払い機能を導入し、ユーザーにシームレスな「ガスレス」体験を提供します。

この強力な機能により、dAppsはガスの複雑さを抽象化し、ユーザーのオンボーディングとアプリケーション全体のユーザビリティを向上させることができます。


## 仕組み

ガス代行支払いの仕組みは、標準的なHTTPヘッダーを通じて実装されます。クライアントインスタンスにガス支払い者ウォレットを設定すると、クライアントはブロックチェーンノードに送信するすべての`sendTx`ミューテーションに、自動的に2つの特別なヘッダーを添付します：

* `x-gas-payer-pk`: ガス料金を支払うウォレットの公開鍵。
* `x-gas-payer-sig`: ガス支払い者の秘密鍵で署名されたJSON Web Token (JWT)。このトークンにはトランザクションのハッシュが含まれており、その特定のトランザクションの手数料を支払うというスポンサーからの検証可能な承認として機能します。

ブロックチェーンノードがトランザクションを受信すると、2つの重要な検証を実行します：

1. トランザクション自体に対するユーザーの署名を検証します。
2. ヘッダー内のガス支払い者の署名をトランザクションハッシュと照合して検証します。

両方の署名が有効な場合、トランザクションはユーザーの権限で実行されますが、対応するガス料金はガス支払い者のアカウント残高から差し引かれます。

### ワークフロー図

以下の図は、トランザクションの開始から実行までのガス代行支払いの全フローを示しています：

<!-- DIAGRAM_IMAGE_START:sequence:4:3 -->

![Gas Payment](assets/diagram/core-concepts-gas-payment-01.jpg)

<!-- DIAGRAM_IMAGE_END -->


## 使用例

ガスレストランザクションを有効にするには、スポンサーアカウント用のウォレットインスタンスを作成し、`setGasPayer`メソッドを使用してクライアントに設定するだけです。

```javascript ガス支払い者の設定と使用法 icon=logos:javascript
import Client from '@ocap/client';
import Wallet, { fromRandom } from '@ocap/wallet';

// 1. Betaチェーンに接続するためにクライアントを初期化
const client = new Client('https://beta.abtnetwork.io/api');

// 2. ガス支払い者（アプリケーションのウォレット）用のウォレットを作成
// このウォレットには、トランザクション手数料を賄うのに十分なネイティブトークン（TBA）が必要です。
// テストトークンはフォーセットから入手できます: https://faucet.abtnetwork.io/
const gasPayerWallet = Wallet.fromJSON({
  sk: '...your_sponsor_secret_key...',
  pk: '...your_sponsor_public_key...',
  address: '...your_sponsor_address...',
});

// 3. クライアントインスタンスにガス支払い者を設定
client.setGasPayer(gasPayerWallet);

// 4. エンドユーザー用のウォレットを作成。
const userWallet = fromRandom();

// 5. ユーザーのウォレットを使用してトランザクションを送信。
// トランザクションはユーザーによって署名されますが、ガス料金はgasPayerWalletによって支払われます。
async function performGaslessTransaction() {
  try {
    // 注：新規アカウントは最初の受信トランザクションでオンチェーンに作成されますが、
    // トランザクションを*送信*する前にオンチェーンに存在している必要があります。
    // フォーセットから少額のトークンを送信することで初期化できます。

    const receiverAddress = 'z1...'; // 有効な受信者アドレス
    const hash = await client.transfer({
      to: receiverAddress,
      tokens: [{ value: '0.1' }], // 0.1 TBAを送信
      wallet: userWallet,
    });

    console.log('Gasless transaction successful. Hash:', hash);
    console.log(`Review on explorer: https://beta.abtnetwork.io/explorer/txs/${hash}`);
  } catch (error) {
    console.error('Transaction failed:', error);
  }
}

performGaslessTransaction();
```

この例では、`gasPayerWallet`がコストを負担するため、`userWallet`はネイティブトークンの残高がゼロであってもトランザクションを正常に送信できます。これにより、特にアプリケーションに新たに参加するユーザーにとって、摩擦のない体験が実現します。

---

トランザクションの作成から確定までの全行程を理解するには、[トランザクションのライフサイクル](./core-concepts-transaction-lifecycle.md)のドキュメントを参照してください。
