eth_twc_sdk/lib.rs
1//! # eth-twc-sdk
2//!
3//! **TransferWithCommitment(TWC)** 向け Ethereum クライアント SDK(EIP-712・コントラクト呼び出し・レシート検証)。
4//!
5//! ## Usage
6//!
7//! 1. **TWC アドレス** — 通常ビルドでは [`config`] のソース([`transfer_with_commitment_address`] が返すコンパイル時定数)をデプロイ先に合わせる。`integration-test` 時のみ環境変数 `ETH_TWC_CONTRACT_ADDRESS` を参照します。
8//! 2. **プロバイダ** — Alloy の [`Provider`](alloy::providers::Provider)(例: `ProviderBuilder::new().connect_http(url)`)を用意します。
9//! 3. **送金** — EIP-712 委任なら [`sign`] で署名バンドルを作り [`send_transaction::signature_transfer`] で送信。`msg.sender` 送金なら [`send_transaction::self_transfer`] を直接呼びます。
10//! 4. **検証** — マイニング後のトランザクションハッシュと [`VerifyArgs`] で [`verify`] を呼び、レシート上の `TransferWithCommitmentSent` を照合します。
11//!
12//! `msg.sender` で送金して検証する例(接続チェーンの [`config::transfer_with_commitment_address`] に TWC がデプロイ済みであること)。
13//!
14//! ```ignore
15//! use alloy::primitives::{address, utils::parse_ether, B256};
16//! use alloy::providers::ProviderBuilder;
17//! use eth_twc_sdk::{
18//! send_transaction::self_transfer,
19//! types::SelfSingleTransferArgs,
20//! verify,
21//! VerifyArgs,
22//! };
23//!
24//! #[tokio::main]
25//! async fn main() -> Result<(), eth_twc_sdk::SdkError> {
26//! let provider = ProviderBuilder::new().connect_http("http://127.0.0.1:8545".parse().unwrap());
27//! let from = address!("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266");
28//! let token = address!("0x5FbDB2315678afecb367f032d93F642f64180aa3");
29//! let to = address!("0x70997970C51812dc3A010C7d01b50e0d17dc79C8");
30//! let value = parse_ether("1").unwrap();
31//! let commitment = B256::ZERO;
32//!
33//! let args = SelfSingleTransferArgs {
34//! token,
35//! to,
36//! value,
37//! commitment,
38//! };
39//! let tx_hash = self_transfer::transfer(&provider, from, args).await?;
40//!
41//! verify::verify(
42//! &provider,
43//! tx_hash,
44//! &VerifyArgs {
45//! from,
46//! token,
47//! to,
48//! value,
49//! commitment,
50//! },
51//! )
52//! .await?;
53//! Ok(())
54//! }
55//! ```
56//!
57//! EIP-712 署名を executor が送信し、同じく検証する例(読み取り用 Provider・署名者・executor 用ウォレット付き Provider)。
58//!
59//! ```ignore
60//! use alloy::network::EthereumWallet;
61//! use alloy::primitives::{address, utils::parse_ether, B256};
62//! use alloy::providers::ProviderBuilder;
63//! use alloy::signers::local::PrivateKeySigner;
64//! use eth_twc_sdk::{
65//! send_transaction::signature_transfer,
66//! sign,
67//! types::SingleTransferArgs,
68//! verify,
69//! VerifyArgs,
70//! };
71//!
72//! #[tokio::main]
73//! async fn main() -> Result<(), eth_twc_sdk::SdkError> {
74//! let read_provider =
75//! ProviderBuilder::new().connect_http("http://127.0.0.1:8545".parse().unwrap());
76//!
77//! let sender: PrivateKeySigner =
78//! "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
79//! .parse()
80//! .unwrap();
81//! let executor: PrivateKeySigner =
82//! "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
83//! .parse()
84//! .unwrap();
85//!
86//! let token = address!("0x5FbDB2315678afecb367f032d93F642f64180aa3");
87//! let to = address!("0x70997970C51812dc3A010C7d01b50e0d17dc79C8");
88//! let value = parse_ether("1").unwrap();
89//! let commitment = B256::ZERO;
90//!
91//! let signed = sign::single_transfer(
92//! &read_provider,
93//! &sender,
94//! SingleTransferArgs {
95//! from: sender.address(),
96//! to,
97//! token,
98//! executor: executor.address(),
99//! value,
100//! commitment,
101//! valid_after: None,
102//! valid_before: None,
103//! },
104//! )
105//! .await?;
106//!
107//! let executor_provider = ProviderBuilder::new()
108//! .wallet(EthereumWallet::new(executor.clone()))
109//! .connect_http("http://127.0.0.1:8545".parse().unwrap());
110//! let tx_hash =
111//! signature_transfer::single_transfer(&executor_provider, executor.address(), signed).await?;
112//!
113//! verify::verify(
114//! &read_provider,
115//! tx_hash,
116//! &VerifyArgs {
117//! from: sender.address(),
118//! token,
119//! to,
120//! value,
121//! commitment,
122//! },
123//! )
124//! .await?;
125//! Ok(())
126//! }
127//! ```
128//!
129//! ## Commitment(`B256`)の導出 — 利用者向け注意
130//!
131//! 本クレートは **`commitment` を生成するヘルパを提供しない**。理由は、(1) 外部とランダム nonce を共有するスキームなど、アプリ層のスキーマとの**相互運用性**を SDK で固定しないため、(2) ハッシュ関数の選択を SDK に押し付けず、**ハッシュに関する単一障害点**にならないためである。
132//!
133//! オフチェーンで `commitment` を導出するときは、利用者の責任で **暗号学的にランダムな `r`** と、用途に適した**安全なハッシュ関数 `H`** を選び、少なくとも **`commitment = H(message || r)`** の形(`message` はアプリのスキーマに従うバイト列)を満たすことを推奨する。`H` の具体(例: Keccak-256)や `message` のエンコードは、アプリと合意者間で定義する。
134//!
135//! ## 構成
136//!
137//! | モジュール | 役割 |
138//! |------------|------|
139//! | [`config`] | 決定論 TWC アドレス・EIP-712 / CREATE2 salt 定数 |
140//! | [`sign`] | EIP-712 署名([`Provider`](alloy::providers::Provider) + [`Signer`](alloy::signers::Signer)) |
141//! | [`verify`] | トランザクションレシート上のイベント検証 |
142//! | [`send_transaction::self_transfer`] | `msg.sender` による `transfer` |
143//! | [`send_transaction::signature_transfer`] | 署名付き `transferWithAuthorization` / `cancelAuthorization` |
144//! | [`types`] | 引数・署名済みバンドル・明細型 |
145//! | [`utils`] | チェーン/domain 整合の検証ヘルパ |
146//! | [`events`] | ログデコード用イベント型 |
147//!
148//! オンチェーン呼び出し・型生成は **alloy** に依存します。
149//!
150//! ## クイックリンク
151//!
152//! - エラー型: [`SdkError`](署名 API は [`SdkError::FromSignerMismatch`] / [`SdkError::AuthorizerSignerMismatch`] で `from` / `authorizer` と署名キーの不一致を検出)
153//! - 検証用イベント引数: [`VerifyArgs`]
154//!
155//! ## ドキュメントの生成
156//!
157//! ```text
158//! cargo doc --no-deps
159//! ```
160//!
161//! 非公開モジュール(`contract` など)を含める場合は `--document-private-items` を付けます。
162
163pub mod config;
164
165pub use config::transfer_with_commitment_address;
166pub mod error;
167pub mod sign;
168pub mod types;
169pub mod utils;
170pub mod verify;
171
172/// レシート解析用の `sol!` イベント定義。
173pub mod events;
174
175/// トランザクション送信(自己送金・署名付き)。
176pub mod send_transaction;
177
178/// Ethereum アドレス([`alloy::primitives::Address`] の再エクスポート)。
179pub use alloy::primitives::Address;
180/// EIP-712 ドメイン([`alloy::sol_types::Eip712Domain`] の再エクスポート)。
181pub use alloy::sol_types::Eip712Domain;
182/// SDK 全体で用いるエラー型。
183pub use error::SdkError;
184pub use types::signed_data::{
185 SignedBatchTransferWithCommit, SignedCancelAuthorization, SignedTransferWithCommit,
186 SignedUniCommitTransfers,
187};
188/// [`verify`] に渡すオフチェーン検証引数。
189pub use verify::VerifyArgs;
190/// `sol!` が生成する `TransferWithCommitmentSent` イベント型([`SolEvent::decode_log`](alloy::sol_types::SolEvent::decode_log) の `.data` と同型)。
191pub use events::TransferWithCommitmentSent;
192pub use utils::{
193 assert_provider_supported_chain, assert_signed_domain_matches_client_and_config,
194 assert_signed_domain_matches_provider_and_config,
195};
196
197mod contract;