0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

React Native + Expo + Supabaseで海外送金・FX・暗号資産ルート比較MVPを作って学んだ5つのこと

0
Posted at

はじめに

私はFinTech・暗号資産業界で8年以上、オペレーションやプロダクト業務に関わってきました。

一方で、私は伝統的な意味でのソフトウェアエンジニアではありません。

それでも今回、AI-assisted workflowを活用しながら、海外送金・FX・暗号資産・ステーブルコインのルートを比較するプロダクト TransferIQ を企画し、Web版とAndroid版まで公開しました。

使用した主な技術は以下です。

  • React Native
  • Expo
  • JavaScript
  • Supabase
  • REST API
  • Netlify
  • GitHub

この記事では、単なる「作ってみた」ではなく、実際にMVPを作る過程で特に難しかった設計上のポイントを5つ共有します。


1. 「手数料比較」ではなく「最終受取額比較」にする

最初に考えたのは、送金サービスの手数料を一覧表示することでした。

しかし、実際に比較を始めると、すぐに問題が見つかりました。

例えば、同じ1,000 USDを送金する場合でも、以下の条件によって結果が変わります。

  • 送金手数料
  • FXスプレッド
  • 支払方法
  • 受取方法
  • 金額帯
  • 国別条件

単純化すると、例えば次のようなケースがあります。

Provider A

  • Fee: 5 USD
  • FX Rate: 1 USD = 4.90 BRL
  • Final Receive: 4,875 BRL

Provider B

  • Fee: 10 USD
  • FX Rate: 1 USD = 4.98 BRL
  • Final Receive: 4,930 BRL

手数料だけを見ると、Provider Aの方が安く見えます。

しかし、最終的な受取額を見ると、Provider Bの方が多く受け取れる可能性があります。

この経験から、比較の中心を「手数料」から「推定最終受取額」に変更しました。

つまり、ユーザーにとって本当に重要なのは、

いくら払うか

だけではなく、

最終的にいくら受け取れるか

だと考えました。

これはTransferIQの設計で最も重要な判断の一つでした。


2. 共通FX Benchmarkを1つ持たないと比較結果が壊れる

次に問題になったのが、FX基準値です。

例えば送金サービスA、B、Cを比較する時に、それぞれ異なるタイミング、異なるAPI、異なる基準レートを使うと、公平な比較になりません。

あるProviderだけ古いレートを使い、別のProviderだけ新しいレートを使っていれば、UI上では比較できているように見えても、実際には基準が揃っていません。

そこで、まず共通のFX benchmarkを持つ構造にしました。

概念的には以下のような形です。

const midMarketRate = 5.20;

const providers = [
  {
    name: "Provider A",
    fee: 5,
    spread: 0.012,
  },
  {
    name: "Provider B",
    fee: 8,
    spread: 0.006,
  },
];

Providerごとの概算レートは、例えば次のように計算できます。

function estimateProviderRate(midRate, spread) {
  return midRate * (1 - spread);
}

さらに、最終受取額の簡略モデルは次のようになります。

function estimateReceiveAmount({
  sendAmount,
  fee,
  midRate,
  spread,
}) {
  const netSendAmount = sendAmount - fee;
  const providerRate = midRate * (1 - spread);

  return netSendAmount * providerRate;
}

もちろん、実際のサービスではこれだけでは足りません。

さらに以下のような要素を考慮する必要があります。

  • fixed fee
  • variable fee
  • amount band
  • corridor adjustment
  • payout method
  • payment method
  • dynamic pricing

重要なのは、各サービスを比較する前に、共通のBenchmarkを1つ持つことでした。

これがないと、UI上はきれいでも比較ロジック自体が不公平になります。

私はこの部分を作りながら、比較サービスでは「データをたくさん集めること」よりも、「何を共通基準にするか」の方が重要な場合があると学びました。


3. 「Live API」と表示してはいけないデータがある

これはかなり重要な学びでした。

最初は、外部データを使っているため、

  • Live API
  • Official API
  • Official Rate

のようなラベルを付けたくなります。

しかし実際には、すべての送金会社が一般公開されたリアルタイムQuote APIを提供しているわけではありません。

また、公開市場データとProvider固有のQuoteは全く別のものです。

そこで、データの性質を明確に分離することにしました。

現在は例えば、以下のように区別しています。

  • Live exchange market
  • Provider benchmark
  • Market benchmark
  • Variable pricing
  • P2P pricing
  • Crypto only

公開取引所の市場データと、Providerのベンチマーク推定値は同じものではありません。

市場基準値とP2P価格推定も同じではありません。

そのため、UIでも同じラベルにしないようにしました。

JavaScript上では、例えば次のようにデータタイプを分けられます。

const DATA_BADGE_TYPES = {
  LIVE_MARKET: "Live exchange market",
  PROVIDER_BENCHMARK: "Provider benchmark",
  MARKET_BENCHMARK: "Market benchmark",
  VARIABLE_PRICING: "Variable pricing",
  P2P_PRICING: "P2P pricing",
  CRYPTO_ONLY: "Crypto only",
};

この設計変更は、単なるUI改善ではありません。

主な目的は以下です。

  • ユーザーの誤解を減らす
  • データの性質を正直に伝える
  • 推定値と市場データを区別する
  • プロダクトへの信頼を守る

特にFinTech領域では、

どのデータがリアルタイムなのか

どのデータが推定なのか

どのデータがProvider固有のQuoteなのか

を明確にする必要があると学びました。

便利に見せるために強い表現を使うより、データの限界を正直に表示する方が重要だと考えています。


4. FiatとCryptoを同じ比較エンジンに入れるとUXが複雑になる

TransferIQでは、Fiat-to-Fiatだけでなく、以下のルートも扱いたいと考えました。

  • Remittance
  • FX
  • Crypto
  • Stablecoin
  • P2P
  • Crypto-to-Crypto

しかし、ここでUI設計が急に複雑になりました。

例えば、

USD → BRL

と、

USDT → BTC

は全く異なる比較です。

前者では、ユーザーは法定通貨を送って法定通貨を受け取ります。

そのため、重要なのは、

  • Sending Currency
  • Receiving Currency

です。

一方、後者では暗号資産同士を交換します。

そのため、

  • Sending Coin
  • Receiving Coin

という表現の方が自然です。

そこで、モードによって入力ラベルを切り替える必要がありました。

概念的には次のような実装です。

const isCryptoMode = mode === "crypto";

const fromLabel = isCryptoMode
  ? "Sending coin"
  : "Sending currency";

const toLabel = isCryptoMode
  ? "Receiving coin"
  : "Receiving currency";

さらに、Crypto Convertではフィルタの意味も重要でした。

例えば、

USDT → BTC

の場合、ユーザーが最終的に受け取るのはBTCです。

そのため、結果画面のコインフィルタは「送信コイン」ではなく「最終受取コイン」を基準にした方が自然です。

一見すると小さな違いですが、ユーザーの操作感は大きく変わります。

FiatとCryptoを同じ画面に入れる場合、単純に通貨コードだけ置き換えるのでは不十分でした。

ユーザーが、

  • 何を送るのか
  • 何を受け取るのか
  • どの市場を比較しているのか
  • 最終結果がFiatなのかCryptoなのか

を明確に理解できる必要があります。

この部分は、実際に作ってみて初めて複雑さを実感したポイントでした。


5. AI-assisted developmentでも「仕様を決める人」は必要

今回の開発ではAIをかなり活用しました。

私は伝統的なソフトウェアエンジニアではないため、AI-assisted workflowは非常に重要でした。

AIは、例えば以下のような作業を高速に支援できます。

  • コンポーネント作成
  • UI修正
  • エラー調査
  • API接続コードの作成
  • 条件分岐の修正
  • リファクタリング
  • 多言語テキストの整理

しかし、実際にやってみて分かったのは、

AIにコードを書かせること

と、

正しいプロダクトを作ること

は別問題だということです。

例えば、次のような判断は人間側に残ります。

  • 何を比較するのか
  • 何を比較しないのか
  • どのデータを信頼するのか
  • どの表現が誤解を生むのか
  • どの機能を削るのか
  • MVPで何を優先するのか
  • どの問題を今は解かないのか

実際、TransferIQでも何度も仕様変更をしました。

例えば、「Official API」という表現を削除しました。

理由は、すべてのProviderについて公式リアルタイムQuote APIを直接利用しているわけではないからです。

また、単純なFee比較ではなく「Final Receive Amount」を比較の中心に変更しました。

Crypto Convertでも、フィルタの意味を「送信コイン」ではなく「最終受取コイン」に変更しました。

AIはコード生成を加速してくれます。

しかし、以下の判断は依然として非常に重要です。

  • Product Decision
  • Data Definition
  • Risk Judgment
  • UX Priority

AI-assisted developmentであっても、最終的に「何を作るか」を決める役割は必要だと感じました。

むしろAIによって実装速度が上がるほど、間違った仕様も速く作れてしまいます。

そのため、Product Decisionの重要性は下がるのではなく、逆に上がる可能性があると考えています。


現在のアーキテクチャ

非常に簡略化すると、現在の構造は以下のようなイメージです。

  1. React Native / Expo App
  2. Comparison Logic
  3. FX Benchmark / Crypto Market / Provider Models
  4. Estimated Route Results
  5. Official Provider Quote Page

比較ロジックでは、異なる性質のデータをできるだけ分離して扱います。

例えば、

  • FX benchmark
  • Public crypto market data
  • Provider benchmark
  • Variable pricing model
  • P2P pricing

などです。

そして最終的に、ユーザーには推定されたRoute Resultsを表示します。

重要な原則は次の3つです。

  • No custody
  • No payment execution
  • No firm quote

つまりTransferIQ自体は、

  • ユーザー資金を保管しない
  • 送金を実行しない
  • 最終確定Quoteを提供しない

という設計です。

基本コンセプトは、

Estimate first. Official quote before sending.

です。

ユーザーはまず異なるルートを比較し、その後、実際に送金や取引を行う前に公式ProviderまたはExchangeで最終Quoteを確認します。


今後改善したいこと

現在、特に改善したいのは次の領域です。

  1. 実際の受取額データの精度向上
  2. Provider別データ品質の可視化
  3. Corridor別の比較精度向上
  4. Stablecoin off-ramp routeの拡張
  5. より多くの実ユーザーフィードバック収集

今後、実際のQuoteや受取結果に近いデータをさらに蓄積できれば、単純な手数料比較ではなく、

  • Route quality
  • Final receive amount
  • Corridor differences
  • Payout options
  • Data confidence

まで含めた比較に近づけると考えています。

最終的には、単純な「手数料比較」ではなく、より広い意味での Route Intelligence に近いものを目指しています。


おわりに

非エンジニア出身でも、AI-assisted workflowを使えば実際のプロダクトを作ることは可能です。

今回、私は企画、UX、データ構造、比較ロジック、アプリ開発、Web公開、Google Playリリースまで進めました。

ただし、AIだけでは解決しない問題も多くありました。

特に重要だったのは以下です。

  • データ定義
  • 比較基準
  • UX設計
  • 表現の正確性
  • 仕様の優先順位

AIは「作る速度」を上げてくれます。

しかし、「何を作るべきか」「何を表示すべきではないか」を決める役割は依然として必要です。

今回作ったプロジェクトはこちらです。

現在も改善を続けています。

特に以下の分野に関心がある方の技術的なフィードバックを歓迎します。

  • 海外送金比較
  • FX
  • Crypto
  • Stablecoin
  • P2P
  • React Native / Expo
  • AI-assisted development
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?