Transfer
ウォレットを接続した後、to アドレスへ SUI を送信する PTB を構築し、useSignAndExecuteTransaction で実行します。
この例は
devnetを使用しています。
ライブエディタ
function Transfer() { const account = useCurrentAccount(); const { mutate: signAndExecuteTransaction, isPending } = useSignAndExecuteTransaction(); const { data: balance } = useSuiClientQuery('getBalance', { owner: account?.address ?? '' }, { enabled: !!account }); const [to, setTo] = useState(''); const [mist, setMist] = useState('1000000'); const [digest, setDigest] = useState(''); const [error, setError] = useState(''); if (!account) { return ( <div className="alert alert--info"> 最初にウォレットを接続してください(右上のウォレットアイコン)。 </div> ); } const hasValidTo = /^0x[0-9a-fA-F]+$/.test(to) && to.length >= 4; const hasValidAmount = /^[0-9]+$/.test(mist) && mist !== '0'; const canSubmit = hasValidTo && hasValidAmount && !isPending; return ( <div style={{ maxWidth: 980 }}> <div style={{ marginBottom: 10, fontSize: 12, fontWeight: 700, color: 'var(--ifm-color-emphasis-700)' }}> 一般 </div> <div style={{ border: '1px solid var(--ifm-color-emphasis-300)', borderRadius: 12, padding: 16, background: 'var(--ifm-background-surface-color)', }} > <div className="row" style={{ rowGap: 12 }}> <div className="col col--3"> <div className="text--muted" style={{ fontSize: 12 }}> ネットワーク </div> <div style={{ fontWeight: 700 }}> <code>sui:devnet</code> </div> </div> <div className="col col--3"> <div className="text--muted" style={{ fontSize: 12 }}> 残高 </div> <div style={{ fontWeight: 700 }}> {balance ? ( <> <code>{balance.totalBalance}</code> <span className="text--muted">mist</span> </> ) : ( <span className="text--muted">読み込み中…</span> )} </div> </div> <div className="col col--6"> <div className="text--muted" style={{ fontSize: 12 }}> 送信元 </div> <div style={{ wordBreak: 'break-all' }}> <code>{account.address}</code> </div> </div> </div> </div> <div className="margin-top--lg" style={{ marginBottom: 10, fontSize: 12, fontWeight: 700, color: 'var(--ifm-color-emphasis-700)' }}> トランザクション入力 </div> <div style={{ border: '1px solid var(--ifm-color-emphasis-300)', borderRadius: 12, padding: 16, background: 'var(--ifm-background-surface-color)', }} > <div className="row" style={{ rowGap: 16 }}> <div className="col col--8"> <label className="form-label" style={{ display: 'block' }}> <b>送信先アドレス</b> </label> <input className="input input--lg" value={to} onChange={(e) => setTo(e.target.value.trim())} placeholder="0x..." /> {!to ? null : hasValidTo ? null : ( <div className="margin-top--xs text--danger" style={{ fontSize: 13 }}> 有効な 0x アドレスを入力してください。 </div> )} </div> <div className="col col--4"> <label className="form-label" style={{ display: 'block' }}> <b>金額 (mist)</b> </label> <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}> <input className="input input--lg" value={mist} onChange={(e) => setMist(e.target.value.trim())} inputMode="numeric" /> <button type="button" className="button button--secondary button--sm" onClick={() => { if (!balance) return; setMist(String(balance.totalBalance)); }} disabled={!balance} > 最大 </button> </div> {!mist ? null : hasValidAmount ? null : ( <div className="margin-top--xs text--danger" style={{ fontSize: 13 }}> 金額は正の整数である必要があります。 </div> )} </div> </div> <div className="margin-top--lg" style={{ display: 'flex', gap: 12, alignItems: 'center', flexWrap: 'wrap' }}> <button className="button button--warning button--lg" disabled={!canSubmit} onClick={() => { setError(''); setDigest(''); if (!hasValidTo) return; if (!hasValidAmount) return; const tx = new Transaction(); const [coin] = tx.splitCoins(tx.gas, [mist]); tx.transferObjects([coin], to); signAndExecuteTransaction( { transaction: tx, chain: 'sui:devnet' }, { onSuccess: (result) => setDigest(result.digest), onError: (e) => { const message = e?.message ?? String(e); if (message.includes('No valid gas coins found')) { setError( 'このアドレスの Devnet にガスコインが見つかりません。ウォレットのネットワークを Devnet に切り替えてフォーセットから SUI を取得してから、再試行してください。', ); return; } setError(message); }, }, ); }} > {isPending ? '実行中…' : '実行'} </button> <div style={{ flex: 1, minWidth: 260 }}> <div className="text--muted" style={{ fontSize: 12 }}> 結果 </div> {digest ? ( <div style={{ marginTop: 4, display: 'flex', gap: 10, alignItems: 'center', justifyContent: 'space-between', flexWrap: 'wrap' }}> <code style={{ wordBreak: 'break-all' }}>{digest}</code> <a href={`https://suiexplorer.com/txblock/${digest}?network=devnet`} target="_blank" rel="noreferrer" style={{ fontWeight: 600, whiteSpace: 'nowrap' }} > 開く </a> </div> ) : ( <div className="text--muted" style={{ fontSize: 13, marginTop: 4 }}> 実行後に結果がここに表示されます。 </div> )} </div> </div> </div> {error ? <div className="alert alert--danger margin-top--md">{error}</div> : null} </div> ); } render(<Transfer />);
結果
Loading...