flare-smart-accounts について
XRPL ウォレット保有者が FLR を持たずに Flare 上で操作できる Flare Smart Accounts を解説する情報提供スキルです。Payment やメモの形式、金庫操作、カスタムコントラクト呼び出しを扱い、取引実行や署名鍵の管理は行いません。
主な機能
- 01XRPL から Flare へのアカウント抽象化の説明
- 02Payment reference の命令形式
- 03FXRP の転送と償還命令
- 04Firelight と Upshift の金庫操作
- 05メモ命令によるカスタムコントラクト呼び出し
- 06セキュリティと復旧のガイダンス
活用シーン
- 01XRPL Payment 命令への対応実装
- 02FXRP 金庫の入金・出金の統合
- 03Flare アカウント向けカスタム呼び出しの準備
- 04取引フローと安全上の制約の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ flare-foundation/ flare-ai-skills --skill flare-smart-accountsインストール後、Claude Code で/flare-smart-accountsを入力して読み込まれたか確認します。
同梱ファイルreference.md
詳細
セキュリティと安全な使用
このスキルは情報提供のみを目的としています。
- ブロックチェーン取引は実行しません
- 署名キーの保存や送信は行いません
- 署名はすべて、ユーザーが管理するウォレットで行う必要があります
- 外部データは開発者が検証する必要があります
- セキュアなキー管理はユーザーの責任です
実行可能なコードや、自動化された金融アクションは含まれていません。
Flare Smart Accounts
スマートアカウントとは
Flare Smart Accounts は、XRPL ユーザーがFLR トークンを保有せずに Flare チェーン上でアクションを実行できる、アカウント抽象化を提供します。
各 XRPL アドレスには、そのアドレスだけが制御できる固有の Flare 上のスマートアカウントが割り当てられます。
主な利点:
- FLR 不要: ユーザーは XRPL ウォレットのみで Flare を利用できます
- 単一のトランザクション: すべての指示は XRPL Payment トランザクションにエンコードされます
- オペレーター管理のガス: リレイヤーサービスが Flare 上でのトランザクション実行を処理します
- 証明ベースのセキュリティ: 支払いのアテステーションと検証に Flare Data Connector(FDC)を使用します
仕組み
Flare Smart Accounts は、相互に補完する次の 2 つのフローをサポートしています。
証明ベースのフロー(支払い参照)
- XRPL の指示: ユーザーはオペレーターの XRPL アドレスに
Paymentを送信し、メモフィールドの支払い参照として 32 バイトの指示をエンコードします。 - 証明の生成: オペレーターは FDC に
Paymentアテステーションを要求します。 - オンチェーン実行: オペレーターは FDC の証明を渡して、
MasterAccountControllerのexecuteInstruction(またはreserveCollateral)を呼び出します。
コントラクトは証明を検証し、ユーザーのスマートアカウントを取得(または作成)して、支払い参照をデコードし、要求されたアクションを実行します。
ダイレクトミント(メモ)フロー
- ユーザーは、スマートアカウントに FXRP をミントする FAssets の Core Vault の XRPL アドレスに(FAssets のミントに従って)
Paymentを送信します。このとき、指示をメモフィールドに格納します。 - エグゼキューターは
executeDirectMintingを呼び出します。FAssets のAssetManagerはMasterAccountControllerに FXRP をミントし、handleMintedFAssetsを呼び出します。 MasterAccountControllerは FAssets をユーザーのPersonalAccountに送金し、必要に応じてエグゼキューター手数料を支払い、メモの指示をディスパッチします(メモオペコードを参照)。
ミントは FAssets のミントであり、CRT の指示ではありません。 ユーザーによる FXRP のミントでは、Smart Accounts の担保予約(CRT)指示は使用されなくなりました。ミントするには、FAssets のミントの説明に従い、メモまたは宛先タグを付けて XRPL
Paymentを Core Vault に送信します。従来の CRT 指示(以下の0x00、0x10、0x20)とその CLI エンコーダーは古いツールに残っている場合がありますが、推奨されるミント方法ではありません。1 回の支払いでミントとアクションを実行するには、メモフィールドのカスタム指示を使用してください。
重要: スマートアカウントを対象とする XRPL トランザクションでは、宛先タグを使用してはいけません。宛先タグを指定すると、FAssets のダイレクトミントはスマートアカウントではなくタグの所有者に入金します。
支払い参照の構造(32 バイト)
すべての指示は次の構造に従います。
| バイト位置 | フィールド | 説明 |
|---|---|---|
| バイト 1 | 指示 ID | 1 つ目のニブル=タイプ(0-F)、2 つ目のニブル=コマンド(0-F) |
| バイト 2 | ウォレット ID | オペレーターが割り当てるウォレット識別子(未割り当ての場合は 0 を使用) |
| バイト 3-12 | 値 | エンコードされた 10 バイトの数量(FXRP または XRP のロット数) |
| バイト 13 以降 | パラメーター | 指示固有のデータ |
指示タイプ — バイト形式の詳細
FXRP 指示(タイプ 0x0_)
0x00 — 担保の予約 (legacy CRT)
FXRP を発行するための担保を予約します。レガシー: FAssets の発行(XRPL から Core Vault への支払い)を推奨します。ここでは、古いツールや過去の統合向けに説明しています。
| Bytes | Field | Description |
|---|---|---|
| 1 | 0x00 | 命令 ID |
| 2 | walletId | ウォレット識別子 |
| 3-12 | value | 発行するロット数(10 bytes) |
| 13-14 | agentVaultId | エージェント Vault 識別子(2 bytes) |
| 15-32 | — | 任意の値(無視されます) |
例: 0x0000000000000000000000010001000000000000000000000000000000000000
- 命令:
00(FXRP の担保予約) - ウォレット ID:
00 - 値:
00000000000000000001(1 ロット) - エージェント Vault ID:
0001
0x01 — FXRP の送金
FXRP を Flare アドレスに送金します。
| Bytes | Field | Description |
|---|---|---|
| 1 | 0x01 | 命令 ID |
| 2 | walletId | ウォレット識別子 |
| 3-12 | value | 送金する FXRP の数量(10 bytes) |
| 13-32 | recipientAddress | 送金先の Flare アドレス(20 bytes) |
例: 0x01000000000000000000000af5488132432118596fa13800b68df4c0ff25131d
- 命令:
01(FXRP の送金) - 値:
000000000000000000000a(10 FXRP) - 受取人:
0xf5488132432118596fa13800b68df4c0ff25131d
0x02 — FXRP の償還
FXRP を XRPL 上の XRP に償還します。
| Bytes | Field | Description |
|---|---|---|
| 1 | 0x02 | 命令 ID |
| 2 | walletId | ウォレット識別子 |
| 3-12 | value | 償還するロット数(10 bytes) |
| 13-32 | — | 任意の値(無視されます) |
Firelight 命令(Type 0x1_)
Firelight は stXRP の利回りを提供する Vault プロトコルです。
0x10 — 担保の予約+預け入れ (legacy CRT)
FXRP の発行と Firelight Vault への預け入れをまとめて行います。レガシー: FAssets の発行の後に 0x11 の預け入れ命令を使用するか、1 回の支払いで発行と預け入れを行うにはメモフィールドのカスタム命令を推奨します。
| Bytes | Field | Description |
|---|---|---|
| 1 | 0x10 | 命令 ID |
| 2 | walletId | ウォレット識別子 |
| 3-12 | value | ロット数(10 bytes) |
| 13-14 | agentVaultId | エージェント Vault 識別子(2 bytes) |
| 15-16 | vaultId | Firelight Vault 識別子(2 bytes) |
| 17-32 | — | 任意の値(無視されます) |
0x11 — 預け入れ
既存の FXRP を Firelight Vault に預け入れます。
| Bytes | Field | Description |
|---|---|---|
| 1 | 0x11 | 命令 ID |
| 2 | walletId | ウォレット識別子 |
| 3-12 | value | 預け入れる FXRP の数量(10 bytes) |
| 13-14 | — | 任意の値(無視されます) |
| 15-16 | vaultId | Firelight Vault 識別子(2 bytes) |
| 17-32 | — | 任意の値(無視されます) |
0x12 — 償還(出金の開始)
Firelight Vault からの出金を開始します。
| Bytes | Field | Description |
|---|---|---|
| 1 | 0x12 | 命令 ID |
| 2 | walletId | ウォレット識別子 |
| 3-12 | value | 出金する数量(10 bytes) |
| 13-14 | — | 任意の値(無視されます) |
| 15-16 | vaultId | Firelight Vault 識別子(2 bytes) |
| 17-32 | — | 任意の値(無視されます) |
0x13 — 出金の受け取り
Firelight Vault で保留中の出金を完了します。
| Bytes | Field | Description |
|---|---|---|
| 1 | 0x13 | 命令 ID |
| 2 | walletId | ウォレット識別子 |
| 3-12 | value | 受け取る数量(10 bytes) |
| 13-14 | — | 任意の値(無視されます) |
| 15-16 | vaultId | Firelight Vault 識別子(2 bytes) |
| 17-32 | — | 任意の値(無視されます) |
Upshift 命令(Type 0x2_)
Upshift は、出金に時間制限がある別の Vault プロトコルです。
0x20 — 担保予約+預け入れ (legacy CRT)
FXRP のミントと Upshift ボールトへの預け入れをまとめて行います。レガシー: FAssets のミントの後に 0x21 の預け入れ命令を使う方法、または 1 回の支払いでミントと預け入れを行うためのメモフィールド・カスタム命令を優先してください。
| バイト | フィールド | 説明 |
|---|---|---|
| 1 | 0x20 | 命令 ID |
| 2 | walletId | ウォレット識別子 |
| 3-12 | value | ロット数(10 バイト) |
| 13-14 | agentVaultId | エージェントボールト識別子(2 バイト) |
| 15-16 | vaultId | Upshift ボールト識別子(2 バイト) |
| 17-32 | — | 任意の値(無視されます) |
0x21 — 預け入れ
既存の FXRP を Upshift ボールトに預け入れます。
| バイト | フィールド | 説明 |
|---|---|---|
| 1 | 0x21 | 命令 ID |
| 2 | walletId | ウォレット識別子 |
| 3-12 | value | 預け入れる FXRP の数量(10 バイト) |
| 13-14 | — | 任意の値(無視されます) |
| 15-16 | vaultId | Upshift ボールト識別子(2 バイト) |
| 17-32 | — | 任意の値(無視されます) |
0x22 — 償還リクエスト
Upshift ボールトからの引き出しをリクエストします(待機期間が始まります)。
| バイト | フィールド | 説明 |
|---|---|---|
| 1 | 0x22 | 命令 ID |
| 2 | walletId | ウォレット識別子 |
| 3-12 | value | 引き出す数量(10 バイト) |
| 13-14 | — | 任意の値(無視されます) |
| 15-16 | vaultId | Upshift ボールト識別子(2 バイト) |
| 17-32 | — | 任意の値(無視されます) |
0x23 — 請求
待機期間の終了後に引き出しを完了します。
| バイト | フィールド | 説明 |
|---|---|---|
| 1 | 0x23 | 命令 ID |
| 2 | walletId | ウォレット識別子 |
| 3-12 | value | YYYYMMDD 形式の日付(例:2025 年 12 月 18 日の場合は 20251218) |
| 13-14 | — | 任意の値(無視されます) |
| 15-16 | vaultId | Upshift ボールト識別子(2 バイト) |
| 17-32 | — | 任意の値(無視されます) |
メモのオペコード(ダイレクトミントフロー)
FAssets のダイレクトミント経路を通じて FXRP をスマートアカウントに直接ミントする場合、XRPL メモの先頭バイトには次のいずれかのオペコードが含まれます。
| メモのオペコード | アクション | 説明 |
|---|---|---|
0xFE | カスタム命令 | keccak256(PackedUserOperation) をコミットする 42 バイトのメモ。バイト列はエグゼキューターによってオフチェーンで配信されます |
0xFF | メモフィールド・カスタム命令 | abi.encode(PackedUserOperation) 全体をメモにインラインで格納します(約 1024 バイトを上限とします) |
0xE0 | メモをスキップ | 対象の XRPL トランザクションのメモを、次回のダイレクトミント時にスキップするよう指定します。executeDirectMintingWithData がリバートした際に FXRP を回収するために使用します。詳しくは失敗時の処理と復旧を参照してください |
0xE1 | ノンスを早送り | 部分的なフローまたは放棄されたフローの後に停止したパーソナルアカウントのメモ命令ノンスを進めます。詳しくは停止したノンスの早送りを参照してください |
0xE2 | エグゼキューター手数料を置換 | 停止した XRPL トランザクションのエグゼキューター手数料を置き換える値に設定します |
0xD0 | エグゼキューターを固定 | 特定のエグゼキューターアドレスをパーソナルアカウントに固定します |
0xD1 | エグゼキューターの固定を解除 | パーソナルアカウントからエグゼキューターの固定を解除します |
カスタム命令 — 詳細
カスタム命令を使うと、XRPL ユーザーは XRPL の Payment を通じて Flare 上の任意のコントラクト呼び出しを実行できます。パーソナルアカウントは、EIP-4337 形式の executeUserOp エントリポイントを公開します。
Call Struct
struct Call {
address target; // Contract address to call
uint256 value; // FLR to send with the call
bytes data; // Encoded function calldata
}
function executeUserOp(Call[] calldata _calls) external payable;
PackedUserOperation
カスタム命令は EIP-4337 の PackedUserOperation としてパッケージ化されます。必要なフィールドは 3 つだけです。
sender— パーソナルアカウントのアドレス(getPersonalAccount(xrplAddress))と一致する必要がありますnonce— 現在のメモノンス(getNonce(personalAccount))と一致する必要がありますcallData—abi.encodeCall(IPersonalAccount.executeUserOp, (calls))
2 つのバリアント
カスタムインストラクション(0xFE)— 推奨:
42 バイトのメモレイアウト:
| バイト | フィールド | 説明 |
|---|---|---|
0 | 0xFE | インストラクション ID |
1 | walletId | ウォレット識別子 |
2-9 | executorFeeUBA | エグゼキューター手数料(ビッグエンディアンの uint64) |
10-41 | userOpHash | keccak256(abi.encode(userOp)) |
ユーザーは完全な PackedUserOperation のバイト列をオフチェーンでエグゼキューターに渡します。エグゼキューターは、msg.value = sum(call.value) として AssetManager の executeDirectMintingWithData(proof, data) を呼び出します。コントローラーは実行前に keccak256(_data) == userOpHash を検証します。これにより、バッチサイズに関係なく XRPL メモを 42 バイトに保てます。
executeDirectMintingWithData は完全にアトミックです。1 回の Flare トランザクションで、個人アカウントに FXRP をミントし、ユーザーオペレーションをディスパッチします。いずれかのステップでリバートが発生した場合(ハッシュの不一致、無効な nonce、内部コールの失敗、msg.value の不足)、トランザクション全体がロールバックされ、FXRP はミントされません。また、UserOperationExecuted イベントも発生しません。失敗時の処理と復旧を参照してください。
メモフィールドカスタムインストラクション(0xFF)— よりシンプルな単一アクター方式:
メモレイアウト(ヘッダー 10 バイト+全ペイロード):
| バイト | フィールド | 説明 |
|---|---|---|
0 | 0xFF | インストラクション ID |
1 | walletId | ウォレット識別子 |
2-9 | executorFeeUBA | エグゼキューター手数料(ビッグエンディアンの uint64) |
10+ | userOpData | abi.encode(PackedUserOperation) |
完全な PackedUserOperation をメモに埋め込みます。任意のインデクサーが executeDirectMinting(proof) を介してリレーできます。XRPL のメモ上限 1024 バイトが適用されます。
TypeScript の例(カスタムインストラクション 0xFE)
import { encodeFunctionData } from "viem";
const calls = [
{
target: counterAddress,
value: 0n,
data: encodeFunctionData({
abi: counterAbi,
functionName: "increment",
args: [],
}),
},
];
const callData = encodeFunctionData({
abi: personalAccountAbi,
functionName: "executeUserOp",
args: [calls],
});
const nonce = await publicClient.readContract({
address: MASTER_ACCOUNT_CONTROLLER_ADDRESS,
abi: masterAccountControllerAbi,
functionName: "getNonce",
args: [personalAccountAddress],
});
const userOp = {
sender: personalAccountAddress,
nonce,
callData,
// remaining fields empty — not validated on-chain
initCode: "0x",
callGasLimit: 0n,
verificationGasLimit: 0n,
preVerificationGas: 0n,
gasFees: "0x",
paymasterAndData: "0x",
signature: "0x",
};
// Deliver userOp bytes to executor off-chain, build 42-byte memo with keccak256 hash
0xFE を使う場合: バッチが大きい場合、コールのペイロードを XRPL 上で非公開にしておきたい場合、またはエグゼキューターを運用している場合。
0xFF を使う場合: コールバッチが約 1024 バイト以内に収まり、エグゼキューターとの連携を避けたい場合。
詳しいトレードオフについては、カスタムインストラクションの比較を参照してください。
ミントせずに ERC-20 残高を移動する:手数料のみのカスタムインストラクション
個人アカウントには、FXRP のミントとは無関係な ERC-20 残高(例:USDT0)がすでにある場合があります。その残高を送金またはスワップするには、netMintAmountXrp: 0 を指定した 0xFE カスタムインストラクションを作成します。XRPL の支払いは直接ミント手数料とエグゼキューター手数料のみを賄うため、executeDirectMintingWithData は FXRP をミントせずにユーザーオペレーションをディスパッチします。
const memoOnlyAmountXrp = await computeDirectMintingPaymentAmountXrp({
netMintAmountXrp: 0,
});
以降のフローは、同じ 3 ステップの 0xFE プロトコルです。Call[] バッチ(例:USDT0.transfer(recipient, amount)、または USDT0 → FXRP のスワップを行うための approve + SparkDEX exactInputSingle)をエンコードし、42 バイトのメモに keccak256(PackedUserOperation) を記録して、手数料のみの XRPL 支払いを送信します。その後、エグゼキューターが FDC 証明を取得し、executeDirectMintingWithData を呼び出します。Control USDT0 ガイドでは、flare-viem-starter を使った、実行可能な完全版の例(残高確認、送金、スワップのスクリプト)を確認できます。
失敗時の処理と復旧
0xFE / 0xFF のカスタムインストラクションを使った直接ミントのフローは、Flare 側でアトミックに実行されます。executeDirectMintingWithData(または 0xFF の場合は executeDirectMinting)がリバートすると、Flare トランザクション全体がロールバックされます。
- Flare 上ではFXRP はミントされず、ユーザーオペレーションも実行されません。
UserOperationExecutedイベントも発生しません。 - XRPL の支払いは取り消されません。直接ミントが正常に完了するまで、元の XRP はコアボールトに留まります。ユーザーの XRPL ウォレットへ自動返金されることはありません。
想定されている UX は、1 回のアトミックなトランザクションでミントとユーザーオペレーションを実行することです(例:1 回のコールで FXRP をミントして EOA に出金する)。そのため、この失敗経路はまれなはずです。
よくあるリバートの原因
handleMintedFAssets 内の検証または実行が失敗すると、呼び出し全体がリバートされます。
sender≠ 個人アカウント →InvalidSendernonce≠ 現在のメモの nonce(getNonce) →InvalidNonce- メモの長さ ≠ 42 バイト →
InvalidMemoData;不明な命令バイト →InvalidInstructionId keccak256(_data)≠ メモのハッシュ →CustomInstructionHashMismatch(expected, actual)- executor の
msg.value< 内部call.valueの合計 → 内部のCallFailedが発生し、トランザクション全体がリバートされます - アカウントに固定 executor(
getExecutor)が設定されていて、呼び出し元がその executor ではない →WrongExecutor - 内部呼び出しのいずれかがリバート →
CallFailedとして通知され、トランザクション全体がリバートされます
ダイレクトミント側のエラー(レート制限、受取人の誤り、スマートアカウントマネージャーにルーティングされる未認識のメモ)については、Minting Troubleshooting ガイドの「スマートアカウントパス」セクションを参照してください。
「XRPL トランザクションは成功したのに、命令が実行されませんでした」 — 多くの場合、次の 2 つの原因が考えられます。
- 個人アカウントに資金がありません。 個人アカウントから値を送信するカスタム命令(LayerZero の手数料など)は、そのアカウントのネイティブ残高が空の場合、XRPL の送金自体は成功したように見えてもリバートされます。スクリプトを実行する前に、Coston2 faucet から EOA ではなく個人アカウントのアドレスに資金を送ってください。アドレスの導出方法については、State Lookup を参照してください。
- 別のトランザクションを確認しています。 エントリーポイントは
MasterAccountControllerなので、ディスパッチされた呼び出しは、自分の EOA からのトップレベルのトランザクションではなく、個人アカウントの内部トランザクションとして実行されます。ブロックエクスプローラーで、個人アカウントのトップレベルのトランザクション一覧だけでなく、内部トランザクションを確認してください。
ミントの失敗/停滞後の復旧
ミントがリバートされた(または executor が証明を送信しなかった)うえ、停滞中のトランザクション ID がオンチェーンでまだ使用されていない(isTransactionIdUsed が false を返す)場合、ユーザーは元のユーザーオペレーションを実行せずに FXRP を復旧できます。
- 停滞中のトランザクション ID を対象として、メモのオペコードが
0xE0(メモをスキップ) の XRPLPaymentを送信します。そのメモは0xFE/0xFFと同じ 42 バイトのヘッダー形式を使用します:[0xE0 | walletId(1B) | executorFeeUBA(8B) | targetTxId(32B)]。この送金には正の純ミント額を含める必要があります(手数料のみのダイレクトミントはオンチェーンでリバートされます)。そのため、この送金自体で少量の FXRP(例:純額 1 XRP)がミントされます。 - executor は復旧用の送金に対して
executeDirectMintingWithData(recoveryProof, "0x")を呼び出します。これにより個人アカウントでIgnoreMemoSetが発行され、停滞中のトランザクション ID に関連付けられます。 - executor は元の停滞中の送金に対して
executeDirectMintingWithDataを再送信します。スキップフラグが設定されているため、コントローラーは元のユーザーオペレーションをディスパッチせずに、個人アカウントへ FXRP をミントします。再試行時に、0xFEの停滞中の送金には元の ABI エンコード済みPackedUserOperationバイト列を_dataとして渡してください。0xFFの場合は"0x"で十分です。
復旧した FXRP は、標準の FAssets 命令(0x02 で換金)を使うか、現在の getNonce を使った新しいユーザーオペレーションで移動できます。関連する復旧用オペコードは 0xE1(nonce の早送り)および 0xE2(停滞中の送金の executor 手数料を置き換え)です。Recover Stuck Mint Transaction guide を参照してください。
停止した nonce の早送り(0xE1)
0xE0 による復旧では、停止した支払いから FXRP をミントしますが、元のユーザー操作は意図的にスキップされます。memo-instruction nonce はそのまま残り、放棄された PackedUserOperation を指しています。新しい 0xFE/0xFF 命令を作成する前に、0xE1(nonce の早送り)を使って、放棄されたスロットを飛び越えるよう getNonce を進めてください。停止した支払いが実際にミント済み(isTransactionIdUsed == true)であることを確認してから実行してください。まだミントされていない場合は、0xE1 ではなく、まず 0xE0 による復旧を実行してください。
- memo オペコード
0xE1を指定した XRPLPaymentを送信します。他の復旧オペコードと同じ 42 バイトのヘッダー形式を使用します:[0xE1 | walletId(1B) | executorFeeUBA(8B) | newNonce(32B)]。0xE0と同様に、この支払いには正の純ミント額が必要です。手数料のみのダイレクトミントは、オンチェーンでリバートします。 - 送信前にクライアント側で
newNonceを検証します。現在のgetNonceより厳密に大きい必要があり、増分(newNonce - currentNonce)はtype(uint32).max以下でなければなりません。オンチェーンで増分が無効な場合、InvalidNonceIncreaseでリバートします。 - エグゼキューターは
0xE1の支払いに対してexecuteDirectMintingWithData(proof, "0x")を呼び出します。ユーザー操作は実行されないため、_dataは不要です。成功すると、レシートにはNonceIncreased(personalAccount, newNonce)イベントが含まれ、UserOperationExecutedイベントは含まれません。 - 次の
0xFE/0xFFユーザー操作を、nonce == getNonce(personalAccount)(現在はnewNonce)として作成します。
実行可能な手順をすべて含むガイドについては、Fast-Forward Nonce guide を参照してください。放棄された 0xFE → 0xE0 → 0xE1 の復旧デモも含まれています。
nonce 重複による失敗の回避
よくあるリバートの原因は、短時間に2 件の XRPL 支払いを送信し、それぞれに異なる PackedUserOperation を含めながら、どちらも同じ getNonce 値を使用することです(たとえば、どちらかのミントが確定する前に作成した 2 件の出金試行)。特定の nonce を使用できる支払いは 1 件だけです。どちらかのミントが先に実行されると成功して nonce が増加し、もう一方は InvalidNonce でリバートし、その XRP は復旧されるまで Core Vault に残ります。これを避けるには、次の点に注意してください。
- XRPL 支払いごとに
getNonceを一度読み取ってください。並行するフロー間で再利用しないでください。 - 最初のミントが確定するか、リバートしたことを確認してから、新しいユーザー操作を含む別の支払いを作成してください。
- エグゼキューター向け:
AssetManagerがDirectMintingDelayedを発行した場合は、executionAllowedAtまで待ってからexecuteDirectMintingWithDataを再度呼び出してください。遅延したミントを完全な失敗とみなして、ユーザーに重複 nonce の支払いを再送するよう促さないでください。
CLI ツール — 完全なリファレンス
smart-accounts-cli は、スマートアカウントのフロー向けに XRPL トランザクションのペイロードを作成し、XRPL 支払いを送信するための Python ツールです。
インストール
git clone https://github.com/flare-foundation/smart-accounts-cli.git
cd smart-accounts-cli
pip install -r requirements.txt
cp .env.example .env
環境設定(.env)
.env.example を .env にコピーし、そのファイルに記載された値を入力します。通常、テスト用のローカルウォレット認証情報と、XRPL および Flare ネットワークの RPC エンドポイントが含まれます。
セキュリティ: ウォレット認証情報は、安全でユーザーが管理するツールで保管してください。チャットツールや安全でない自動化ツールに貼り付けないでください。XRPL テストネットトークンは XRP Faucets から入手してください。
コマンド構文
./smart_accounts.py <command> <subcommand> [options]
ENCODE コマンド
すべての encode コマンドで --wallet-id を指定できます(デフォルトは 0 です)。
FXRP 操作
レガシーのミント経路。
fxrp-cr(およびbridge mint-tx)は非推奨の担保予約(CRT)フローをエンコードします。smart_accounts.pyに残っている場合もありますが、推奨されるミント経路ではありません。FXRP をミントするには、Mint FXRP ガイドに従い、FAssets minting(Core Vault への XRPL 支払い)を使用してください。CLI ではこの支払いをエンコードしません。以下のfxrp-transferおよびfxrp-redeemコマンドは引き続き使用できます。
# Collateral reservation for minting (legacy CRT — prefer FAssets minting)
./smart_accounts.py encode fxrp-cr --wallet-id 0 --value 1 --agent-vault-id 1
# Transfer FXRP to address
./smart_accounts.py encode fxrp-transfer --wallet-id 0 --value 10 \
--recipient-address "0xf5488132432118596fa13800b68df4c0ff25131d"
# Redeem FXRP to XRP
./smart_accounts.py encode fxrp-redeem --wallet-id 0 --value 1
Firelight の操作
firelight-cr-depositはレガシーです(CRT のミントと入金)。FAssets のミントを行ってからfirelight-depositを実行するか、メモフィールドのカスタム指示を使って、1 回の支払いでミントと入金を行ってください。
# Reserve collateral and deposit to vault (legacy CRT)
./smart_accounts.py encode firelight-cr-deposit --wallet-id 0 --value 1 \
--agent-vault-id 1 --vault-id 1
# Deposit FXRP to vault
./smart_accounts.py encode firelight-deposit --wallet-id 0 --value 10 --vault-id 1
# Initiate withdrawal
./smart_accounts.py encode firelight-redeem --wallet-id 0 --value 10 --vault-id 1
# Claim completed withdrawal
./smart_accounts.py encode firelight-claim-withdraw --wallet-id 0 --value 10 --vault-id 1
Upshift の操作
upshift-cr-depositはレガシーです(CRT のミントと入金)。FAssets のミントを行ってからupshift-depositを実行するか、メモフィールドのカスタム指示を使って、1 回の支払いでミントと入金を行ってください。
# Reserve collateral and deposit to vault (legacy CRT)
./smart_accounts.py encode upshift-cr-deposit --wallet-id 0 --value 1 \
--agent-vault-id 1 --vault-id 2
# Deposit FXRP to vault
./smart_accounts.py encode upshift-deposit --wallet-id 0 --value 10 --vault-id 2
# Request withdrawal (starts waiting period)
./smart_accounts.py encode upshift-request-redeem --wallet-id 0 --value 10 --vault-id 2
# Claim after waiting period (value = date YYYYMMDD)
./smart_accounts.py encode upshift-claim --wallet-id 0 --value 20251218 --vault-id 2
BRIDGE コマンド
XRPL トランザクションを実行します。
オペレーターサービスが Flare へのブリッジを行います。
# Send encoded instruction as XRPL Payment
./smart_accounts.py bridge instruction <encodedInstruction>
# Or read from stdin
<encode_command> | ./smart_accounts.py bridge instruction -
# Send XRP to agent vault for minting (legacy CRT flow, after collateral reservation)
# NOTE: the standard mint path is now an XRPL payment to the Core Vault — see FAssets minting.
./smart_accounts.py bridge mint-tx <transactionHash>
# With --wait flag to wait for confirmation
./smart_accounts.py bridge mint-tx --wait -
DECODE コマンド
指示を確認するために、エンコード操作を逆変換します。
./smart_accounts.py decode <encodedInstruction>
# Or from stdin
<encode_command> | ./smart_accounts.py decode -
コマンドの連結(パイプ処理)
コマンドを連結して、ワークフロー全体を実行します。
# Mint FXRP (reserve + pay in one pipeline)
./smart_accounts.py encode fxrp-cr --wallet-id 0 --value 1 --agent-vault-id 1 \
| ./smart_accounts.py bridge instruction - \
| ./smart_accounts.py bridge mint-tx --wait -
# Mint and deposit to Upshift vault
./smart_accounts.py encode upshift-cr-deposit --wallet-id 0 --value 1 \
--agent-vault-id 1 --vault-id 2 \
| ./smart_accounts.py bridge instruction - \
| ./smart_accounts.py bridge mint-tx --wait -
ワークフローの完全な例
以下のミント手順に関する注記。
fxrp-cr/upshift-cr-depositとbridge mint-txの手順では、**レガシーの担保予約(CRT)**によるミント経路を使用します。現在の統合では、FAssets のミントで FXRP をミントし(Core Vault への XRPL 支払いについてはFXRP のミントを参照)、その後、ここに記載されたミント以外の Smart Accounts の指示(送金、入金、引き出し)を実行してください。これらの例は、CLI による指示とブリッジのパイプ処理を示すために掲載しています。
例 1:FXRP をミントして別のアドレスに送金する
# Step 1: Mint 1 lot of FXRP
./smart_accounts.py encode fxrp-cr --wallet-id 0 --value 1 --agent-vault-id 1 \
| ./smart_accounts.py bridge instruction - \
| ./smart_accounts.py bridge mint-tx --wait -
# Output: sent bridge instruction transaction: 08C2DD9E...
# sent mint tx: CD15241A...
# Step 2: Transfer 10 FXRP to recipient
./smart_accounts.py encode fxrp-transfer --wallet-id 0 --value 10 \
--recipient-address "0xf5488132432118596fa13800b68df4c0ff25131d" \
| ./smart_accounts.py bridge instruction -
# Output: sent bridge instruction transaction: 9D5420C6...
例 2:FAssets の全サイクル(ミント → 入金 → 引き出し → 償還)
# Step 1: Mint and deposit to Upshift vault
./smart_accounts.py encode upshift-cr-deposit --wallet-id 0 --value 1 \
--agent-vault-id 1 --vault-id 2 \
| ./smart_accounts.py bridge instruction - \
| ./smart_accounts.py bridge mint-tx --wait -
# Output: sent bridge instruction transaction: 77539CDE...
# sent mint tx: 3C65E10D...
# Step 2: Request withdrawal from vault
./smart_accounts.py encode upshift-request-redeem --wallet-id 0 --value 10 --vault-id 2 \
| ./smart_accounts.py bridge instruction -
# Output: sent bridge instruction transaction: 33B08253...
# Step 3: Claim withdrawal after waiting period (use correct date)
./smart_accounts.py encode upshift-claim --wallet-id 0 --value 20251218 --vault-id 2 \
| ./smart_accounts.py bridge instruction -
# Output: sent bridge instruction transaction: 8D81F5A2...
# Step 4: Redeem FXRP back to XRP
./smart_accounts.py encode fxrp-redeem --wallet-id 0 --value 1 \
| ./smart_accounts.py bridge instruction -
# Output: sent bridge instruction transaction: FE9D0039...
コアコントラクト:MasterAccountController
MasterAccountController は、スマートアカウントの中心となるコントラクトです。
| 関数 | 目的 |
|---|---|
getPersonalAccount(xrplAddress) | Flare 上のユーザーのスマートアカウントアドレスを取得します(決定論的で、デプロイ前でも利用できます) |
getXrplProviderWallets() | 支払いに使うオペレーターの XRPL アドレスを取得します |
getVaults() | 登録済みの Vault アドレスと種類を一覧表示します |
getAgentVaults() | FAssets エージェントの Vault を一覧表示します |
getNonce(personalAccount) | 現在のメモ指示用 nonce を取得します。PackedUserOperation.nonce はこの値と一致する必要があります |
getExecutor(personalAccount) | パーソナルアカウントに固定された executor を取得します(address(0) は固定されていないことを示します) |
executeInstruction(proof, xrplAddress) | 証明ベースの指示を実行します |
reserveCollateral(xrplAddress, paymentRef, txId) | (レガシー CRT) 担保を予約します(この段階では FDC 証明は不要です)。現在、ユーザーのミントにはこの経路ではなく、FAssets のミントのexecuteDirectMintingを使用します |
executeDepositAfterMinting(reservationId, proof, xrplAddress) | (レガシー CRT) ミント後に担保予約と入金を行う処理の第 2 段階です |
handleMintedFAssets(...) | FXRP がパーソナルアカウントに直接ミントされた際に、AssetManager によって呼び出されます |
TypeScript 統合(Viem)
パッケージ: viem、xrpl。wagmi/viem の型付きコントラクト操作には、@flarenetwork/flare-wagmi-periphery-packageを使用してください。
セットアップ
import { createPublicClient, http } from "viem";
import { flareTestnet } from "viem/chains";
const publicClient = createPublicClient({
chain: flareTestnet,
transport: http(),
});
スマートアカウントの状態を読み取る
// Get user's smart account address
const personalAccount = await publicClient.readContract({
address: MASTER_ACCOUNT_CONTROLLER_ADDRESS,
abi: masterAccountControllerAbi,
functionName: "getPersonalAccount",
args: [xrplAddress],
});
// Get operator XRPL addresses
const operatorAddresses = await publicClient.readContract({
address: MASTER_ACCOUNT_CONTROLLER_ADDRESS,
abi: masterAccountControllerAbi,
functionName: "getXrplProviderWallets",
args: [],
});
// Get registered vaults
const vaults = await publicClient.readContract({
address: MASTER_ACCOUNT_CONTROLLER_ADDRESS,
abi: masterAccountControllerAbi,
functionName: "getVaults",
args: [],
});
// Get FXRP balance
const fxrpBalance = await publicClient.readContract({
address: fxrpAddress,
abi: erc20Abi,
functionName: "balanceOf",
args: [personalAccount],
});
指示を付けて XRPL 支払いを送信する
import { Client, Wallet } from "xrpl";
async function sendInstruction(encodedInstruction: `0x${string}`) {
const operatorAddress = (await getOperatorXrplAddresses())[0];
const instructionFee = await getInstructionFee(encodedInstruction);
const payment = {
TransactionType: "Payment",
Destination: operatorAddress,
Amount: instructionFee,
Memos: [{ Memo: { MemoData: encodedInstruction.slice(2) } }],
};
return await xrplClient.submitAndWait(payment, { wallet: xrplWallet });
}
主な注意事項
-
ロットサイズ: 1 ロット = 10 FXRP(AssetManager で現在のロットサイズを確認してください)
-
値のエンコード: ほとんどの指示では値はロット単位です。Upshift の請求では日付(YYYYMMDD)です。
-
ウォレット ID: Flare オペレーターによって割り当てられていない場合は、0 を使用してください。
-
Upshift の引き出し: 2 段階の処理です(償還をリクエスト → 待機 → 請求)。
-
CLI の実行: CLI は XRPL 側のトランザクションのみを送信します。
Flare 側の処理は、リレイヤー/オペレーターサービスによって行われます。
セキュリティと利用上の考慮事項
このスキルはリファレンスドキュメントのみを提供します。 トランザクションを実行したり、キーを保持したりすることはありません。スマートアカウントのフローを実装またはデバッグするために使用してください。すべての金融取引の実行は、開発者とエンドユーザーの責任です。
サードパーティのデータ(支払いメモ、RPC の状態): XRPL の支払いメモや、RPC エンドポイント(例:XRPL testnet、Coston2)から取得するオンチェーンデータは、信頼できない外部入力です。メモは、このドキュメントに記載されている固定の 32 バイト命令フォーマットに従ってのみデコードし、自由形式のテキストではなく構造化ペイロードとして扱ってください。未加工のメモやトランザクションの内容は、検証済みの型付き値に解析するまで、自由形式の AI 処理に含めないでください。
金融操作とキー: このスキルに含まれるコマンドやコード(CLI の bridge コマンド、submitAndWait など)は、資金を移動させる可能性があります。ウォレットの認証情報は、ユーザーが管理する安全な環境に保管してください。支払いまたはブリッジ命令を実行する際は、必ずユーザーが明示的に開始し、送信前にトランザクションの詳細を確認するようにしてください。
このスキルを使用する場面
- ユーザーが FLR を保有する必要のない、XRPL と Flare 間のインタラクションを実装する場合
- XRPL ユーザーが FXRP をミントしたり、Flare のボールトとやり取りしたりできる dApp を構築する場合
- XRPL から任意のコントラクト呼び出しを行うカスタム命令を作成する場合
- スマートアカウントのフロー、支払い参照、命令のエンコードをデバッグする場合
- MasterAccountController と統合したり、スマートアカウントのイベントを監視したりする場合
- テストや自動化に smart-accounts-cli を使用する場合
追加リソース
- 公式ドキュメントとガイド:reference.md
- 関連スキル:flare-fassets — FAssets のミント、償還、エージェントの詳細について説明しています。