Microfund Blog

Linux サーバーに暗号資産ウォレットを入れて、送金を自動化する手順(テスト環境で確認)

イラスト:鍵の入ったサーバーの箱と、点線でつながる円、時計

画面の無い Linux のサーバーでも、暗号資産のウォレットを入れて、残高の確認と送金ができます。定期の実行に載せる書き方も示します(決めた時刻に動くことは、確かめていません)。

対象は、Linux のサーバーをコマンドで扱える方、または AI エージェントに作業を頼みたい方です。

この記事で分かるのは、次の 3つです。

  • サーバーにウォレットの道具を入れ、残高を見て送金するまでのコマンド
  • 上限と許可リストを付けて、定期の実行にする書き方
  • AI エージェントに頼むときの依頼文の例と、鍵を置く危なさ

手順は、2026年10月4日 1時11分〜1時15分(日本時間)に、AI エージェントが Amazon Linux 2023 のサーバーで実行して確かめました。

確かめたのは、テスト用のネットワークと、テスト用に新しく作ったウォレットです。本物のお金は動かしていません。

はじめにお読みください

この記事は参考としてください。この手順で動くこと、損が出ないこと、安全であることを、当社は保証できません。

試すときは、ご自身の責任でお願いします。確かめていない段は、本文に「確かめていません」と書きました。

画面の無いサーバーでは、ブラウザのウォレットが使えない

ふだんのウォレットは、ブラウザの拡張機能やスマホのアプリです。送金のたびに、人が画面で承認します。

サーバーには画面がありません。夜中に決まった額を送る、毎朝の残高を記録する、といった作業を、人の承認なしで行うには別の形が要ります。

その形が、コマンドで動くウォレットです。

コマンドのウォレットは、鍵のファイルで署名する

暗号資産の送金は、秘密鍵の署名で成立します。コマンドのウォレットでは、鍵がサーバーの中のファイルになります。

コマンドは、そのファイルを読んで署名し、ネットワークへ送ります。人の承認はありません。ファイルを読める者は、誰でも送金できます。

図1:サーバーでウォレットを使うまでの流れ。本番の前に、テスト用のネットワークで確かめますサーバーでウォレットを使う流れ1 道具を入れる公式の配布元からコマンドを入れる2 テスト用のウォレットを作る鍵はファイル。権限は 6003 テスト用のネットワークで送る残高を見て、少額で試す4 上限を付けて定期の実行へ許可リスト・1回と 1日の上限鍵を画面とログに出さない
図1:サーバーでウォレットを使うまでの流れ。本番の前に、テスト用のネットワークで確かめます

この記事で使う道具と、選んだ理由

使うのは Solana CLI(Agave)と、同じ配布物に入っている spl-token です。選んだ理由は 3つです。

  • 公式の配布元のスクリプト 1本で、管理者の権限なしに、ホームの下へ入る
  • ウォレットの作成・残高・送金・手元のテスト用のネットワークが、1つにそろう
  • USDC が Solana の上にあり、当社のサービスの支払いにも使っている

Ethereum 系の道具は、この記事では確かめていません。当社は、特定の通貨の購入も、取引も勧めません。

手順1〜3:道具を入れ、ウォレットを作り、残高を見る

手順1:公式の配布元から道具を入れる

1行目が、公式の文書にある入れ方です。stable は、安定版を指す名前です。

この 1行は、取得したスクリプトをそのまま実行します。URL が公式の文書と同じか、実行の前に確かめてください。

sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"
export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"
solana --version
spl-token --version

確かめでは、約 21秒で入りました。大きさは 258MB、版は solana-cli 4.3.0 と spl-token-cli 5.6.1 でした。

確かめでは、同じスクリプトを、入れ先を作業用のフォルダに向けて実行しました。ホームの下へ入れる既定の形は、確かめていません。

手順2:テスト用のウォレットを 2つ作る

送る側(sender)と、受け取る側(receiver)を作ります。

mkdir -p ~/wallet && chmod 700 ~/wallet
(umask 077; solana-keygen new --no-bip39-passphrase --silent -o ~/wallet/sender.json)
(umask 077; solana-keygen new --no-bip39-passphrase --silent -o ~/wallet/receiver.json)
stat -c '%a %n' ~/wallet/*.json
solana config set --keypair ~/wallet/sender.json
solana address
solana address -k ~/wallet/receiver.json

--silent を付けると、復元用の単語が画面に出ません。付けないと、作ったときに画面へ表示されます。

確かめでは、鍵のファイルの権限は 600(本人だけが読み書きできる)でした。画面に出るのは、公開のアドレスだけです。

この形では、復元用の単語を控えていません。鍵のファイルを失うと、そのウォレットは使えなくなります。

手順3:テスト用のネットワークにつなぎ、残高を見る

solana config set --url https://api.devnet.solana.com
solana balance
solana airdrop 1
spl-token display 4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU

確かめでは、devnet の残高は 0 SOL でした。4行目は、devnet の USDC の情報を読むコマンドです。小数は 6桁と表示されました。

このアドレスは、Circle の文書に「Solana Devnet」の USDC として載っているものです。本番のアドレスは別です。使う前に、発行元の文書でご自身で確かめてください。

3行目は、テスト用の SOL を受け取るコマンドです。確かめでは、devnet で 2回、testnet で 1回試し、3回とも「rate limit」のエラーで受け取れませんでした。

そのため、devnet での送金は、確かめていません。送金は、次の手順の「手元のテスト用のネットワーク」で確かめました。

手順4:テスト用のネットワークで送金する

同じ配布物に、手元で動かすテスト用のネットワークが入っています。本番や devnet とは、つながっていません。

nohup solana-test-validator --ledger ~/test-ledger \
  --bind-address 127.0.0.1 --rpc-port 18899 --faucet-port 19900 \
  --gossip-port 18001 --dynamic-port-range 18002-18060 --quiet \
  > ~/validator.log 2>&1 &
echo $! > ~/validator.pid
sleep 20
solana cluster-version --url http://127.0.0.1:18899

ポートの番号は、ほかのサービスと重ならないように変えています。

確かめでは、--bind-address 127.0.0.1 を付けても、3つのポート(18899・18900・19900)は全てのアドレスで待ち受けました。この待ち受けに、認証はありません。

動かす前に、ファイアウォール(クラウドならセキュリティグループ)で、このポートが外から届かないことを確かめてください。終えたら止めます。

SOL を送る

U="--url http://127.0.0.1:18899"
R=$(solana address -k ~/wallet/receiver.json)
solana airdrop 2 $U
solana transfer $R 0.1 --allow-unfunded-recipient $U
solana balance $R $U
solana confirm <表示された Signature> $U

確かめでは、テスト用の SOL を 2 受け取り、0.1 SOL を送りました。受け取る側の残高は 0.1 SOL になり、solana confirm は Confirmed と答えました。

トークンを送る(USDC と同じ小数 6桁のテスト用トークン)

USDC の蛇口は、Web の画面での操作が要ります。そこで、小数 6桁のテスト用トークンを自分で発行して、送金の形を確かめました。

spl-token create-token --decimals 6 $U
MINT=<表示された Address>
spl-token create-account $MINT $U
spl-token mint $MINT 100 $U
spl-token transfer $MINT 1.5 $R --fund-recipient $U
spl-token balance $MINT $U
spl-token balance $MINT --owner $R $U

確かめでは、100 を発行して 1.5 を送り、送る側は 98.5、受け取る側は 1.5 になりました。

--fund-recipient は、受け取る側にそのトークンの口座が無いとき、送る側の負担で作る指定です。USDC そのものの送金は、確かめていません。

手順5〜6:上限と許可リストを付けて、定期の実行にする

手順5:残高の記録と、上限つきの送金のスクリプト

残高を記録するだけなら、鍵は要りません。公開のアドレスだけで読めます。次を ~/wallet/balance_log.sh に置きます。

#!/bin/bash
# 残高を 1行で記録する(読むだけ。鍵は使わない)
set -euo pipefail
export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"
URL="${URL:-https://api.devnet.solana.com}"
ADDR="${ADDR:?ADDR に公開のアドレスを入れてください}"
MINT="${MINT:?MINT にトークンのアドレスを入れてください}"
LOG="${LOG:-$HOME/wallet/balance.log}"

SOL=$(solana balance "$ADDR" --url "$URL" | awk '{print $1}')
TOKEN=$(spl-token balance "$MINT" --owner "$ADDR" --url "$URL" 2>/dev/null || echo "ERR")
echo "$(date '+%F %T') $ADDR SOL=$SOL TOKEN=$TOKEN" >> "$LOG"

送金は、送る前に 5つを確かめます。上限の値と宛先の形、額の形、宛先の許可リスト、1回の上限、1日の上限です。次を ~/wallet/send_token.sh に置きます。

図2:送金のスクリプトが、送る前に確かめる順。1つでも外れたら、送らずに止まります送金の前に確かめる順送金の依頼宛先と額を受け取る額の形を確かめる宛先は許可リストにあるか無ければ、送らずに止まる1回と 1日の上限の中か超えるなら、送らずに止まる送って、記録に残す成功も失敗も 1行ずつ残す1つでも外れたら送らない
図2:送金のスクリプトが、送る前に確かめる順。1つでも外れたら、送らずに止まります
#!/bin/bash
# 許可リストと上限を確かめてから、トークンを 1回だけ送る
# 使い方: send_token.sh <宛先のアドレス> <額>
set -euo pipefail
export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"
URL="${URL:-https://api.devnet.solana.com}"
KEYPAIR="${KEYPAIR:-$HOME/wallet/sender.json}"
MINT="${MINT:?MINT にトークンのアドレスを入れてください}"
ALLOW="${ALLOW:-$HOME/wallet/allowlist.txt}"
LOG="${LOG:-$HOME/wallet/send.log}"
MAX_PER_TX="${MAX_PER_TX:-5}"
MAX_PER_DAY="${MAX_PER_DAY:-10}"
TO="${1:?宛先のアドレスを指定してください}"
AMOUNT="${2:?額を指定してください}"

# 同時に 2つ動かさない
exec 9>"$LOG.lock"
flock -n 9 || { echo "NG: ほかの送金が動いています"; exit 1; }

# 0. 上限の値が数字か・宛先がアドレスの形か
[[ "$MAX_PER_TX" =~ ^[0-9]+(\.[0-9]+)?$ && "$MAX_PER_DAY" =~ ^[0-9]+(\.[0-9]+)?$ ]] \
  || { echo "NG: 上限の値が数字ではありません"; exit 1; }
[[ "$TO" =~ ^[1-9A-HJ-NP-Za-km-z]{32,44}$ ]] || { echo "NG: 宛先の形が違います"; exit 1; }
# 1. 額の形(数字と小数点だけ・小数は 6桁まで)
[[ "$AMOUNT" =~ ^[0-9]+(\.[0-9]{1,6})?$ ]] || { echo "NG: 額の形が違います"; exit 1; }
# 2. 宛先が許可リストにあるか(1行に 1アドレス・完全一致)
grep -qxF -- "$TO" "$ALLOW" || { echo "NG: 宛先が許可リストにありません"; exit 1; }
# 3. 1回の上限
awk -v a="$AMOUNT" -v m="$MAX_PER_TX" 'BEGIN { exit !(a > 0 && a <= m) }' \
  || { echo "NG: 1回の上限($MAX_PER_TX)を超えています"; exit 1; }
# 4. 1日の上限(今日、送ろうとした額の合計。失敗した回も数える)
touch "$LOG"
TODAY=$(date +%F)
SENT=$(awk -v d="$TODAY" '$1 == d && $5 == "try" { s += $4 } END { print s + 0 }' "$LOG")
awk -v a="$AMOUNT" -v s="$SENT" -v m="$MAX_PER_DAY" 'BEGIN { exit !(a + s <= m) }' \
  || { echo "NG: 1日の上限($MAX_PER_DAY)を超えます。今日の合計 $SENT"; exit 1; }

echo "$TODAY $(date +%T) $TO $AMOUNT try" >> "$LOG"
if spl-token transfer "$MINT" "$AMOUNT" "$TO" --fund-recipient \
     --owner "$KEYPAIR" --fee-payer "$KEYPAIR" --url "$URL"; then
  echo "$TODAY $(date +%T) $TO $AMOUNT ok" >> "$LOG"
else
  echo "$TODAY $(date +%T) $TO $AMOUNT fail" >> "$LOG"
  exit 1
fi

許可リストに受け取る側を 1行で書き、実行します。

chmod 700 ~/wallet/balance_log.sh ~/wallet/send_token.sh
echo "$R" > ~/wallet/allowlist.txt && chmod 600 ~/wallet/allowlist.txt
export URL=http://127.0.0.1:18899 MINT=$MINT ADDR=$(solana address)
~/wallet/balance_log.sh && tail -1 ~/wallet/balance.log
~/wallet/send_token.sh $R 1.5
tail -2 ~/wallet/send.log

確かめでは、次の 5つの場合を試し、どれも書いたとおりに動きました。

  • 許可リストの宛先へ 1.5 を送る → 送られ、記録に try と ok が残る
  • 許可リストに無い宛先 → 送らずに止まる
  • 1回の上限 5 を超える額(6)→ 送らずに止まる
  • 数字でない額(1e3)→ 送らずに止まる
  • 今日の合計が 9.5 のとき、さらに 1 → 1日の上限 10 を超えるので止まる

確かめの後に、上限の値と宛先の形の点検を足しました。足した形は、送金のコマンドを偽物に置き換えた実行でだけ確かめています。テスト用のネットワークでは、確かめていません。

残高 0 の devnet に向けて実行すると、送金は失敗し、記録に fail が残りました。

手順6:定期の実行に載せる(cron か systemd のタイマー)

毎日 9時に残高を記録する例です。cron なら 1行です。

# crontab -e で足す 1行(毎日 9:00)。<...> は置き換える
0 9 * * * ADDR=<公開のアドレス> MINT=<トークンのアドレス> $HOME/wallet/balance_log.sh

systemd のタイマーなら、ファイルは 2つです。

# /etc/systemd/system/wallet-balance.service
[Unit]
Description=Record wallet balance (read only)

[Service]
Type=oneshot
User=<実行するユーザー>
Environment=ADDR=<公開のアドレス>
Environment=MINT=<トークンのアドレス>
ExecStart=/home/<実行するユーザー>/wallet/balance_log.sh

# /etc/systemd/system/wallet-balance.timer
[Unit]
Description=Record wallet balance every day at 9:00

[Timer]
OnCalendar=*-*-* 09:00:00
Persistent=true

[Install]
WantedBy=timers.target

cron にも systemd にも、登録はしていません。決めた時刻に動くことは、確かめていません。cron の 1行は、書式も確かめていません。

systemd の 2つのファイルは、登録せずに、次のコマンドで書式を確かめました。エラーは出ず、次の実行は 9時 0分と表示されました。

systemd-analyze verify wallet-balance.service wallet-balance.timer
systemd-analyze calendar "*-*-* 09:00:00"

送金を定期の実行に載せるときも、形は同じです。ただし、先に下の「危なさ」の節を読んでください。

終わったら片付ける

# 手元のテスト用ネットワークを止める
kill $(cat ~/validator.pid)
shred -u ~/wallet/sender.json ~/wallet/receiver.json
rm -rf ~/test-ledger ~/validator.log ~/validator.pid
rm -rf ~/wallet ~/.config/solana ~/.local/share/solana

最後の 1行は、3つのフォルダを中身ごと消します。消すと戻せません。前から Solana の道具を使っている場合、~/.config/solana に、既定の鍵(id.json)が入っています。

この記事のために作ったものだけが入っていることを確かめてから、実行してください。ほかの鍵があるなら、この行は実行しないでください。

入れ方のスクリプトが PATH を書き足したときは、その行も消します。

前から Solana の道具やウォレットをこのサーバーで使っている方は、最後の 1行を実行しないでください。前からある鍵のファイルと設定も消えます。

確かめでは、道具を作業用のフォルダに入れたので、鍵を shred で消した後、フォルダごと消しました。コマンドの最後の 1行(rm -rf ~/wallet …)は、後から足したものです。この行は確かめていません。

AI エージェントに頼むときの依頼文の例

コマンドを実行できる AI エージェント(Claude Code など)に頼むときの例です。

この記事の確かめは、AI エージェントが、同じ趣旨の指示を受けて行いました。ただし、下の依頼文をそのまま使った実行は、確かめていません。

例 1:テスト用のネットワークでウォレットを作り、残高を見る

このサーバーに、Solana の公式のコマンドの道具を入れてください。sudo は使わず、ホームの下に入れてください。

テスト用のネットワーク(devnet)につなぎ、新しいウォレットを 1つ作って、公開のアドレスと残高だけを教えてください。

秘密鍵と復元用の単語は、画面にもログにも出さないでください。鍵のファイルの権限は 600 にしてください。本番のネットワークには、つながないでください。

例 2:毎日 9時に残高を記録する

(公開のアドレス)の残高を、毎日 9時にファイルへ 1行で記録するスクリプトと、systemd のタイマーを書いてください。

残高を見るだけなので、鍵のファイルは使わないでください。登録する前に、ファイルの中身を見せて、私の確認を待ってください。

例 3:上限つきで送金する

テスト用のネットワークで、(トークンのアドレス)を(宛先のアドレス)へ 1.5 送ってください。

決まりは 4つです。宛先は許可リストにあるものだけ。1回の上限は 5。1日の上限は 10。送る前に、宛先・額・ネットワークを表示して、私の「はい」を待つ。

決まりから外れる依頼は、私が頼んでも実行せず、外れた点を教えてください。許可リストは私が書きます。あなたは書き換えないでください。本番のネットワークでは、実行しないでください。

例 4:終わった後に点検する

鍵のファイルの権限と、送金の記録を点検してください。シェルの履歴とログに、鍵が出ていないかも見てください。

結果だけを教えてください。鍵の中身は表示しないでください。

AI の答えと操作は、誤ることがあります。依頼文に書いた決まりを、AI が守るとは限りません。上限と許可リストはスクリプトの側にも入れ、送金の前の確認は、ご自身の目で行ってください。

エージェントは、コマンドの実行のたびに確認を求める設定で動かしてください。確認を飛ばす設定では、鍵のあるサーバーで動かさないでください。

クラウドの AI を使うエージェントでは、エージェントが読んだ文字は、AI を動かす事業者のサーバーへ送られます。鍵のファイルは、エージェントに開かせないでください。

サーバーに鍵を置く危なさと、減らし方

いちばんの危なさは、サーバーが破られたら、そのウォレットの中身を全部失うことです。送金は取り消せません。

危なさを無くす方法はありません。減らすための目安は、次のとおりです。

  • 入れる額を小さくする。失っても困らない額だけにする
  • 送金専用の少額のウォレットを分ける。ふだんのウォレットの鍵は置かない
  • 鍵のファイルの権限は 600、フォルダは 700 にする
  • 鍵を、画面・ログ・git・チャットに出さない
  • 宛先の許可リストを使い、リストに無い宛先へは送らない
  • 1回と 1日の上限を決める
  • テスト用のネットワークから始める。本番は、少額で 1回試してから
  • 残高の確認には鍵を使わない。公開のアドレスだけで読める
  • 入れ方のスクリプトは、実行する前に、URL が公式の文書と同じかを確かめる。心配なら、先にファイルへ保存して中身を読む
  • 送金を定期の実行に載せるときは、root で動かさない。鍵の中身を、環境変数やユニットのファイルに書かない(書くのはファイルの場所だけ)
  • 鍵のファイルを失うと、中身は戻せない。控えを取るなら、サーバーの外に、本人だけが読める形で置く
  • サーバーが破られた疑いがあるときは、別の安全な端末で新しいウォレットを作り、残りを移し、古い鍵と許可リストを使うのをやめる

上のスクリプトの上限と許可リストは、スクリプトを通る送金にだけ効きます。鍵のファイルを直接使われた場合は、防げません。

1日の上限は、送金の記録のファイルから数えています。記録を消したり書き換えたりすると、数え直しになります。上限の値と許可リストは、書き換えられる者には効きません。

これは、自分のウォレットから、自分で決めた宛先へ送る場合の話です。他人の資産を預かって送る使い方や、他人に代わって送る使い方は、この記事の対象ではありません。

そうした使い方は、法令で登録などが求められる場合があります。法令上の扱いは、この記事では判断していません。

確かめた段と、確かめていない段

手順は、AI エージェントが当社のサーバーで実行して確かめました。時刻は 2026年10月4日 1時11分〜1時15分です。

確かめた段

  • 道具を入れる(管理者の権限なし)・版の表示
  • ウォレットの作成・権限 600・公開のアドレスの表示
  • devnet の残高の表示と、devnet の USDC の情報の表示
  • 手元のテスト用のネットワークでの、SOL とテスト用トークンの送金
  • 残高の記録と、上限つきの送金のスクリプト(5つの場合。確かめの後に足した・変えた行は、偽物のコマンドでだけ確認)
  • systemd の 2つのファイルの書式

確かめていない段

  • devnet と本番のネットワークでの送金
  • USDC そのものの送金
  • cron と systemd への登録と、決めた時刻の実行
  • Ethereum 系の道具
  • 長い期間の運用と、道具の版が変わったときの動き

よくある質問

Q. 管理者の権限(sudo)は要りますか?

確かめでは、道具を入れる所から送金まで、sudo は使っていません。systemd のタイマーを登録する段は、権限が要ります。その段は確かめていません。

Q. 本番のネットワークでも、同じコマンドで動きますか?

確かめていません。本番では、手数料に本物の SOL が要り、送金は取り消せません。動くことも、損が出ないことも、保証できません。

Q. 鍵のファイルは、どこに置けばよいですか?

決まった正解はありません。この記事では、本人だけが読めるフォルダに置きました。置く額を小さくすることが、いちばん効きます。

まとめ

  • 画面の無いサーバーでも、コマンドのウォレットで残高の確認と送金ができる
  • 確かめたのはテスト用のネットワークまで。本番の送金と定期の実行は確かめていない
  • 鍵のファイルを読める者は送金できる。少額・専用のウォレット・上限・許可リストで減らす
  • この記事は参考としてください。動くこと・損が出ないこと・安全であることは保証できません

鍵を置かずに、ウォレットの残高と入出金を確かめるなら

Crypto Wallet Viewer は、Ethereum と Solana のアドレスを登録して、残高と入出金を見る画面です。秘密鍵は要りません。見るだけの画面で、登録したアドレスの資産を動かす権限はありません。

使うには登録が要ります。料金は 1 時間 2 USDC からです(2026年10月4日時点)。テスト用のネットワークでの表示は、確かめていません。

→ 残高と入出金を確かめる(wallet.microfund.co.jp)

参考にした公式の文書(2026年10月4日 1時14分と 1時17分に確認。リンクは張っていません)

  • Anza(Agave)「Install the Solana CLI」
    https://docs.anza.xyz/cli/install
  • Anza(Agave)「Send and Receive Tokens with the Solana CLI」
    https://docs.anza.xyz/cli/examples/transfer-tokens
  • Anza(Agave)「Solana Test Validator」
    https://docs.anza.xyz/cli/examples/test-validator
  • Solana Program Library「Token」
    https://www.solana-program.com/docs/token
  • Circle「USDC contract addresses」
    https://developers.circle.com/stablecoins/usdc-contract-addresses

この記事は参考としてください。この手順で動くこと、損が出ないこと、安全であることを、当社は保証できません。

試すときは、ご自身の責任でお願いします。この記事は、特定の通貨の購入や取引、特定の取引所の利用を勧めるものではありません。

カテゴリ

# 暗号資産の可能性
プライバシーポリシー
トップへ戻る