시작하기 OmniFi와 이 SDK

OmniFi SDK

OmniFi 멀티체인 RWA 트랜치 프로토콜의 TypeScript SDK입니다. 온체인 원장을 화면 단위 메서드로 조회하고, 입금·상환·수령을 단일 호출로 실행합니다.

OmniFi 트랜치 상품이란

하나의 운용 풀에 투자자를 두 층(트랜치)으로 나눠 받는 RWA(실물자산 연계) 상품입니다.

트랜치수익성격
Senior고정 이율 (예: 연 3%)수익을 우선 배분받는 안전 선호층
Junior변동 — 잔여 수익 전부Senior 배분 후 남는 수익과 위험을 갖는 층

투자자는 자산(USDC)을 입금하고 share(지분 토큰)를 받습니다. share 가격은 매 정산(settlement)에서 확정되고, 그 가격으로 입금과 상환이 처리됩니다. 펀드의 기준가(NAV) 산정과 같은 구조입니다.

멀티체인 구조

자산이 입금되는 체인과 원장이 기록되는 체인이 분리되어 있습니다:

  • 스포크(Sepolia) — 유저 트랜잭션이 실행되는 체인. 입금·상환 신청과 수령이 여기서 발생합니다.
  • 허브(Bifrost) — 상품 구성·정산 결과·요청 원장의 정본. 대부분의 조회가 여기서 이루어집니다.

신청된 자산은 브릿지를 통해 허브로 이동해 기록되고, 정산 결과가 다시 스포크로 반영됩니다. 따라서 신청부터 수령 가능까지 시간이 소요되는 것이 정상 동작이며, SDK가 그 사이의 진행 상황을 타임라인으로 제공합니다.

상품 라인업 — 예치형과 바스켓형

테스트베드에는 4개 시나리오가 라이브입니다. A·B·C는 자산을 수익원에 예치해 이자를 쌓는 예치형, D는 mock 주식 8종목(QQQ 미러링) 바스켓을 담는 바스켓형(ETF형)입니다 — 바스켓형은 basketHoldings()로 구성 종목을 조회합니다.

시나리오유형자산체인SDK 진입
A멀티체인 · 예치형USDC허브 + SepoliaOmniFi.create() (기본)
B싱글체인 · 예치형JPYCSepoliaTrancheSDK.create({ set: 'b' })
C싱글체인 · 예치형USDCBifrost 허브TrancheSDK.create({ set: 'c' })
D멀티체인 · 바스켓형USDC (QQQ, 8 names)허브 + RobinhoodOmniFi.create({ productId: OMNIFI_SETS.d.productId })

싱글체인 TrancheSDK도 같은 화면 데이터 메서드를 제공합니다 — priceHistory()·realizedApy()·profitHistory()·faucet(), 그리고 investmentRequests()는 허브 TxRegistry에서 요청 tx 해시(txHash)를 보강합니다.

이 문서의 예시 값은 모두 실제 테스트베드 라이브 응답에서 가져온 것입니다.
Getting Started About OmniFi & the SDK

OmniFi SDK

A TypeScript SDK for the OmniFi multichain RWA tranche protocol. It reads the on-chain ledger through per-screen methods and runs deposit, redeem, and receive as single calls. Every failure is a typed error that carries a display-ready message.

What is an OmniFi tranche product

An RWA (real-world-asset) product that accepts investors into a single managed pool split into two layers (tranches).

TrancheYieldProfile
SeniorFixed rate (e.g. 3% APR)Paid first — lower-risk layer
JuniorVariable — residual yieldTakes what remains after Senior, with the matching risk

Investors deposit the asset (USDC) and receive shares. Share prices are finalized at each periodic settlement, and deposits and redemptions execute at that price. This is the same model as fund NAV pricing.

The multichain layout

  • Spoke (Sepolia) — where user transactions run: deposit/redeem requests and receiving.
  • Hub (Bifrost) — the source of truth for product configuration, settlement results, and the request ledger. Most reads come from here.

Requested funds travel to the hub over a bridge, get recorded, and settlement results propagate back to the spoke. A delay between request and receivable is normal — the SDK exposes the in-between progress as a timeline.

Product line-up — deposit vs basket

Four scenarios are live on the testbed. A·B·C are deposit-type (assets earn yield in sources); D is basket-type (ETF-like — a QQQ-mirroring mock-stock basket, inspect with basketHoldings()).

ScenarioTypeAssetChainsEntry
AMultichain · depositUSDChub + SepoliaOmniFi.create() (default)
BSingle-chain · depositJPYCSepoliaTrancheSDK.create({ set: 'b' })
CSingle-chain · depositUSDCBifrost hubTrancheSDK.create({ set: 'c' })
DMultichain · basketUSDC (QQQ, 8 names)hub + RobinhoodOmniFi.create({ productId: OMNIFI_SETS.d.productId })

The single-chain TrancheSDK ships the same screen-data methods — priceHistory()·realizedApy()·profitHistory()·faucet() — and investmentRequests() enriches each request with its tx hash from the hub TxRegistry.

Every sample value in these docs comes from live testbed responses.
시작하기 Quick Start

Quick Start

설치부터 첫 입금 신청까지의 최소 절차입니다.

1. 설치

shell
pnpm add @omnifi/sdk        # peer: viem

2. SDK 초기화

ts
import { OmniFi, OmniFiError } from '@omnifi/sdk'

const omnifi = await OmniFi.create()   // 최신 상품(시나리오 A · USDC) 자동 발견 — 조회는 이것으로 충분

// 특정(구) 상품을 지정할 때만 — 나머지는 디폴트로 동작
const custom = await OmniFi.create({ productId: 0x0000000200000009 })

볼트·자산·RPC는 모두 기본값이 있고, 주소는 허브 프리컴파일에서 자동으로 발견됩니다. 나머지 옵션(defaultChainId·chains·locale·hubRpcUrl)은 필요할 때만 넘기면 됩니다. 조회 메서드는 지갑 없이 동작합니다.

3. 첫 조회 — 상품 정보

ts
const ov = await omnifi.overview()
console.log(ov.tvl?.formatted, ov.assetSymbol)          // "1,399.97" "USDC" (미정산이면 null)
console.log(ov.tranches[0].aprPercent)                  // 3  (Senior 고정 이율 %)

4. 지갑 연결 — 액션 실행 시에만 필요

ts
omnifi.connect(window.ethereum)   // wagmi 사용 시 connector.getProvider() 결과 전달

5. 첫 입금 신청

ts
try {
  const { txHash, requestId } = await omnifi.deposit('senior', '100.5')
  // 자격 확인·네트워크 전환·approve·신청·영수증 대기가 모두 완료된 상태
} catch (e) {
  if (e instanceof OmniFiError) toast(e.userMessage)
}

6. 이후 흐름 — 폴링으로 상태 갱신

신청 후에는 시스템이 자동으로 진행합니다(브릿징 → 정산 → 전파). myAccount()를 10~15초 간격으로 폴링하면 상태가 processingreceivable로 전환되며, 이때 receive()를 호출하면 완료됩니다.

i전체 흐름은 핵심 개념 › 라이프사이클, 화면 구성 방법은 화면 구성 레시피를 참고하세요.
Getting Started Quick Start

Quick Start

The minimal path from install to a first deposit request.

1. Install

shell
pnpm add @omnifi/sdk        # peer: viem

2. Create the SDK

ts
import { OmniFi, OmniFiError } from '@omnifi/sdk'

const omnifi = await OmniFi.create()   // auto-discovers the latest product (scenario A · USDC)

// only when targeting a specific product — everything else has sane defaults
const custom = await OmniFi.create({ productId: 0x0000000200000009 })

Vaults, assets and RPCs all have defaults — this is enough. Addresses are auto-discovered from the hub precompiles. Other options (defaultChainId · chains · locale · hubRpcUrl) only when you need them. All read methods work without a wallet.

3. First read — product info

ts
const ov = await omnifi.overview()
console.log(ov.tvl?.formatted, ov.assetSymbol)          // "1,399.97" "USDC" (null before first settlement)
console.log(ov.tranches[0].aprPercent)                  // 3  (Senior fixed APR %)

4. Connect a wallet — actions only

ts
omnifi.connect(window.ethereum)   // with wagmi: pass connector.getProvider()

5. First deposit

ts
try {
  const { txHash, requestId } = await omnifi.deposit('senior', '100.5')
  // whitelist check, chain switch, approve, request, receipt — all done
} catch (e) {
  if (e instanceof OmniFiError) toast(e.userMessage)
}

6. Afterwards — poll for state

Once requested, the system proceeds automatically. Poll myAccount() every 10–15 s; the state moves processingreceivable, then call receive() to finish.

시작하기 핵심 개념

핵심 개념

SDK 전반에 반복되는 규칙입니다. 나머지는 레퍼런스에서 찾아 쓰면 됩니다.

① Amount — 모든 금액의 공통 형태

type
interface Amount {
  raw: bigint        // 온체인 원본 값
  decimals: number
  symbol: string     // 'USDC' | 'oSR' …
  formatted: string  // '1,399.97' — 절사·천단위, 화면 표시용
}

화면 출력은 `${a.formatted} ${a.symbol}`, 입력은 십진 문자열 "100.5"입니다. 어느 쪽에서도 bigint를 직접 다루지 않습니다.

필드규칙
formatted절사(내림) + 천단위 구분. 기본 소수 4자리, TVL은 2자리 — 잔액 999.9999가 "1,000"으로 반올림돼 보이는 문제 방지
raw · decimals온체인 원본과 자릿수 — "전량" 입력(formatUnits(raw, decimals))과 정밀 비교 외에는 쓸 일 없음
symbol단위 심볼 — 입금량·지급액은 자산(USDC), share 수량은 share 토큰(oSR·oJR 등)으로 자동 결정

② 에러 모델 — 실패의 단일 형태

모든 실패는 OmniFiError로 전달됩니다. e.code로 분기하고 e.userMessage(한국어 완성 문장)를 그대로 표시합니다. 원본 오류는 e.cause — 디버깅 전용이며 화면에 노출하지 않습니다. 전체 코드 표는 에러 처리 페이지에 있습니다.

i"데이터 없음"과 "조회 실패"는 구분됩니다 — 없음은 null/빈 배열(정상), 실패는 OmniFiError(재시도 UI 대상)입니다.

③ 라이프사이클 — 유저 액션은 신청과 수령 두 가지

범례: 유저 액션(tx 서명) 시스템 자동

정산은 주기적으로 실행됩니다(60분 주기, 종료 20분 전 신청 마감). 마감 이후 신청은 다음 회차로 배정됩니다 — 확정 예정 시각은 항상 overview().nextSettlementAt이 기준입니다.

!신청 후 취소는 불가능합니다 (크로스체인 제약). 특히 redeem() 호출 전 확인 모달이 UX 요구사항입니다.

④ 가격은 정산 확정치입니다

SDK가 제공하는 가격·TVL은 실시간 시세가 아니라 최근 정산에서 확정된 값입니다. 화면에는 기준 시각(overview().settledAt)을 반드시 병기합니다. 예상 수령량(estimate*)에도 같은 이유로 "예상" 한정어가 필요합니다.

Getting Started Core Concepts

Core concepts

The rules that recur across the SDK. Everything else is reference lookup.

① Amount — the shape of every value

type
interface Amount {
  raw: bigint
  decimals: number
  symbol: string
  formatted: string  // '1,399.97' — floored, thousand-separated, display-ready
}

Render `${a.formatted} ${a.symbol}`; input is a decimal string. Neither side touches bigint.

② The error model

Every failure is an OmniFiError. Branch on e.code, display e.userMessage. The original error lives in e.cause — debugging only. Full table: Error Handling.

i"No data" and "read failure" are distinct — absence is null/empty (normal); failure is an OmniFiError (retry UI).

③ Lifecycle — users act exactly twice

Legend: user action automatic

Settlement runs on a schedule (60-minute cycles; orders close 20 minutes before cycle end). Late requests roll to the next round — overview().nextSettlementAt is the authoritative ETA.

!Requests cannot be cancelled. A confirmation modal before redeem() is a UX requirement.

④ Prices are settlement-finalized

Prices and TVL are values finalized at the latest settlement — not live quotes. Always show settledAt, and prefix estimate* results with "estimated".

시작하기 프로세스 단계 · 용어

프로세스 단계 · 용어

입금·상환이 신청부터 수령까지 어떤 단계를 거치는지, 각 단계를 무엇이라 부르고 SDK의 어떤 필드로 확인하는지 정리한 문서입니다.

요청 상태 3값

표준 상태한국어 라벨SDK status의미
Pending정산 대기'processing'유저가 입금·상환을 신청한 뒤 처리를 기다리는 단계. 브릿징·회차 배정이 자동으로 진행되며, 유저가 할 일은 없습니다
Receivable수령 가능'receivable'입금·상환 처리가 끝나 유저가 수령할 수 있는 단계. 수령 버튼(receive())을 노출합니다 (온체인 7540의 Claimable — claimDeposit 등 코드 함수명은 원명 유지)
Received수령 완료수령 후 'none'유저가 수령까지 마쳐 요청이 완료된 상태. 이후 이 요청은 진행중 화면에서 사라지고 내역에만 남습니다

입금 단계 ↔ SDK

depositRequest신청 완료유저 tx
bridging자금 공급 중자동 · 상세 뷰
queued정산 대기자동 · 기본 표시
settlement정산 확정자동 · 수량 확정
shareReceivable수령 가능Receivable
shareReceived수령 완료유저 tx
단계 코드UX 라벨SDK에서 보는 법
depositRequest입금 신청 완료deposit() 반환(txHash·requestId) · activity() steps "신청 완료 ✓"
bridging자금 공급 중activity() steps "브릿징 → 허브 도착 → 수익원 전달 → 공급 반영" + 단계별 txHash — 상세 뷰 전용
queued정산 대기status 'processing'의 기본 표시 — overview().nextSettlementAt 병기
settlement정산 확정activity().phase "정산 확정" — share 수량이 여기서 처음 확정
shareReceivable수령 가능status 'receivable' + amount(확정 share)
shareReceived수령 완료receive() 반환 received

상환 단계 ↔ SDK

redeemRequest상환 신청 완료유저 tx · 취소 불가
bridging브릿징자동 · 지급 재원 준비
queued정산 대기자동
settlement정산 확정자동 · 지급액 확정
collateralReceivable수령 가능Receivable
collateralReceived수령 완료유저 tx · share 소각

SDK 매핑은 입금과 동일합니다(redeem()activity()/myAccount()receive()). 차이는 두 가지: 지급액 문구는 가격 모드 종속이라 모드 중립 기본 표현이 지급 예정액 (estimateRedeem()도 "예상" 한정어 필수), 수령 시 escrow share가 소각됩니다.

화면에 직결되는 5가지 규칙

  • 취소는 없습니다 — 입금·상환 모두 크로스체인 취소 미지원. 취소 버튼·상태를 만들지 말고, 신청 확인 모달에서 "신청 후 취소 불가"를 고지하세요 (SDK에도 취소 API가 없습니다).
  • 미결제 요청은 트랜치·방향당 1건 — 앞 요청 수령 전 새 신청은 revert. status !== 'none'이면 신청 버튼을 비활성하는 근거입니다.
  • share 토큰은 수령 시점에 발행 — Receivable의 share는 아직 지갑 잔액이 아닙니다. 잔액 표기는 지갑 share + 수령 대기 share 합산으로.
  • Pending 금액은 운용 전 — 수익이 붙지 않습니다. "정산 확정 시점부터 운용 시작"을 명시.
  • 가격·수량 확정 전에는 "예상" 한정어estimate*() 결과와 신청~정산 구간 share 수량 표시에 필수.

정산 사이클 (시스템 프로세스)

trigger정산 개시봇/Auto Pilot
collectNAV 수집허브+전 스포크
record확정·기록가격 확정 tx
finalize확정 반영스포크 전파

유저 화면에는 정산 회차(settlementRound)와 다음 정산 예정 시각(nextSettlementAt)만 노출합니다. 사이클 크로스체인 진행은 omnifi.inner.settlementProgress(round)(운영 뷰 전용).

온체인 단계 레퍼런스 (프리컴파일 enum)

TxRegistry 프리컴파일이 각 단계에 부여하는 uint8 코드enum명입니다. SDK는 이 코드를 한국어 표준어(TimelineStep.label)와 enum명(TimelineStep.labelEn)으로 함께 노출합니다 — enum명이 크로스팀 문의의 정본입니다(예: "CollectBridgeExecuted가 롤백됐다").

RequestStep — 요청 단계 (get_request.request_steps · adapter_legs)

코드enum명한국어 (입금 / 상환)의미
1Requested신청 완료유저 서명 tx로 요청 접수 — escrow 이동·requestId 발급
2RequestBridgeExecuted브릿징접수 체인 → 허브 자산·지시 브릿지 실행 (Spoke-vault만)
3RequestQueued허브 도착허브 원장 기록·정산 회차 배정
4AdapterBridgeExecuted수익원 전달 / 재원 회수수익원 어댑터 체인으로 자금 브릿지 (원격 체인만 — 로컬은 생략)
5AdapterApplied공급 반영 / 회수 반영어댑터에 공급(입금)·회수(상환) 반영
6RequestCompleted처리 완료요청 자금이 허브·필요 어댑터 체인까지 모두 도달
i상환은 자금을 공급이 아니라 회수하므로 4·5의 한국어 라벨만 방향이 반대입니다 — enum명(AdapterBridgeExecuted·AdapterApplied)은 입금·상환 공통입니다.

SettlementStep — 정산 사이클 단계 (get_settlement.spoke_chains[].steps)

코드enum명한국어의미
0Queued정산 대기회차 배정됨, 아직 개시 전
1SettleStarted정산 개시사이클 발동 (settle_started_tx)
2CollectBridgeExecutedNAV 수집 전달허브 → 스포크 NAV 수집 지시 브릿지
3NavReportedNAV 수집스포크에서 NAV 산출·보고
4ResponseBridgeExecutedNAV 회신스포크 → 허브 NAV 회신 브릿지
5NavReceivedNAV 확정허브에서 전 스포크 NAV 수신·집계 완료
6RequestsApproved승인 기록워터폴·가격 확정 후 요청별 승인 기록 (steps에는 안 나옴 — get_request.settlement_id로 판단)
7FinalizeBridgeExecuted확정 반영 전달허브 → 볼트 체인 정산 결과(분배) 브릿지
8SettleApplied확정 반영볼트 체인에 share 발행·소각·지급액 전환 반영 (Receivable 전환)
9Settled정산 완료사이클 전체 완료 (정산 레벨 상태 — 체인별 steps에는 안 나옴)

WhitelistStep — 화이트리스트 전파 (get_whitelist.steps)

코드enum명한국어의미
1WhitelistRequested변경 접수허브 정본에 grant/revoke 기록
2BridgeExecuted브릿지 전송허브 → 스포크 전파 브릿지 (Spoke-vault만)
3WhitelistApplied반영 완료스포크 전파본 반영 — 액션 종료
i브릿지 단계(코드 2·4·7 등)는 CCCP 롤백(Reverted)으로도 확정될 수 있습니다 — settlementStatus().bridges·TimelineStep.failed가 성공/롤백 전체 시도를 노출합니다. 롤백 상태값은 CCCP SocketEventStatus(3 Executed · 4 Reverted)입니다.

피해야 할 표현

금지·제한대신 쓸 것이유
예치입금(유저→상품) / 공급(상품→수익원)방향이 다른 별개 행위
출금 (상환 의미)상환(redeem) / 수령(receive)withdraw는 어댑터 회수 용어와 충돌
셰어 · 지분 토큰share (번역 금지)ERC-4626/7540 공식 용어
브릿지 대기 중 (차단 상태로)자금 공급 중 / 자금 회수 중브릿징은 유저를 막는 단계가 아님
에폭settlement 주기 / 정산 회차epoch은 수익원 어댑터 로컬 용어
NAV (한정어 없이)share 가격 (유저 뷰)NAV는 층위 구분 필수
명사 자리의 settlesettlement 사이클·주기·가격settle은 동사·함수 참조 전용

용어 계층 (디자이너 회의 기준)

계층용도용어
L1 공용어회의·화면 라벨 — 설명 없이 통용입금 · 상환 · 정산 · 수령 · 공급 · 회수 · 브릿징 + 상태 3개(정산 대기 · 수령 가능 · 수령 완료)
L2 도메인첫 사용에 한 줄 설명share · 트랜치/시니어/주니어 · settlement 가격 · 지급 예정액
L3 구현기획·개발 문서 전용 — 화면 노출 금지단계 코드 · escrow(라벨은 "잠금") · 워터폴 · 대기 제외 금액 · NAV 층위
iSDK의 라벨(statusLabel·stageLabel·activity().phase)은 전부 L1 표준어로 나갑니다 — 화면에 그대로 쓰면 표준 준수가 됩니다.
Getting Started Process Stages & Terms

Process stages & terminology

What stages a deposit or redemption goes through from request to receive, what each stage is called, and which SDK field surfaces it.

Deposit stages ↔ SDK

depositRequestRequesteduser tx
bridgingFunds movingauto · detail view
queuedAwaiting settlementauto · default
settlementSettledauto · amount fixed
shareReceivableReceivable
shareReceivedReceiveduser tx

Mapping: deposit() returns txHash/requestId → activity() carries the bridging/supply timeline with per-step txHash (detail view only) → status 'processing' displays as "awaiting settlement" with nextSettlementAt'receivable' + confirmed amountreceive(). Redeem is symmetric; its payout wording defaults to estimated payout (pricing-mode dependent).

Five rules that shape screens

  • No cancellation — cross-chain cancel is unsupported for both flows; say so in the confirmation modal. The SDK has no cancel API.
  • One outstanding request per tranche × direction — disable the request button whenever status !== 'none'.
  • Share tokens mint at receive time — display balance as wallet shares + receivable shares.
  • Pending amounts earn nothing yet — mark them "not yet deployed".
  • Qualify unconfirmed numbers as "estimated" — applies to all estimate*() output.

On-chain step reference (precompile enums)

The uint8 code and enum name the TxRegistry precompile assigns to each step. The SDK surfaces both the Korean label (TimelineStep.label) and the enum name (TimelineStep.labelEn); the enum name is the canonical id for cross-team communication (e.g. "CollectBridgeExecuted rolled back").

RequestStep

CodeEnumMeaning
1RequestedRequest accepted (escrow + requestId)
2RequestBridgeExecutedBridge from receiving chain to hub (Spoke-vault only)
3RequestQueuedRecorded on hub ledger, round assigned
4AdapterBridgeExecutedBridge to the yield adapter chain (remote chains only)
5AdapterAppliedSupplied (deposit) / withdrawn (redeem) at the adapter
6RequestCompletedFunds reached hub and all required adapter chains

SettlementStep

CodeEnumMeaning
0QueuedRound assigned, not started
1SettleStartedCycle started (settle_started_tx)
2CollectBridgeExecutedHub → spoke NAV-collect bridge
3NavReportedSpoke computes/reports NAV
4ResponseBridgeExecutedSpoke → hub NAV-response bridge
5NavReceivedHub received/aggregated all spoke NAVs
6RequestsApprovedPer-request approvals recorded (not in steps — use get_request.settlement_id)
7FinalizeBridgeExecutedHub → vault-chain distribution bridge
8SettleAppliedApplied on vault chain (Receivable)
9SettledWhole cycle done (settlement-level, not per-chain)

WhitelistStep

CodeEnumMeaning
1WhitelistRequestedgrant/revoke recorded on hub
2BridgeExecutedHub → spoke propagation bridge (Spoke-vault only)
3WhitelistAppliedApplied to spoke copy — action done
iBridge steps (codes 2, 4, 7…) may resolve to a CCCP rollback (Reverted). settlementStatus().bridges and TimelineStep.failed expose the full success/rollback attempt history (CCCP SocketEventStatus: 3 Executed · 4 Reverted).

Avoid these terms

AvoidUse insteadWhy
"deposit" for fund deploymentdeposit (user→product) / supply (product→yield source)Different directions
"withdraw" for user exitsredeem / receivewithdraw is adapter vocabulary
translating "share"share (as-is)ERC-4626/7540 official term
"waiting for bridge" as a blocking statefunds being supplied / withdrawnBridging never blocks the user
epochsettlement period / roundepoch is adapter-local
bare "NAV"share price (user views)NAV needs a level qualifier
iAll SDK labels (statusLabel · stageLabel · activity().phase) are emitted in the L1 standard vocabulary — rendering them verbatim keeps your UI compliant.
데이터 API overview()

overview() — 상품 페이지 데이터 단일 조회

상품 페이지에 필요한 전부: 트랜치 구성·이율·가격·TVL·정산 일정.

overview(): Promise<Overview>

파라미터 없음 · 지갑 불필요 · 실패 시 OmniFiError

반환 필드 — Overview 전체

필드타입의미 · null 조건 · 예시
productIdnumber허브 원장의 상품 식별자 (uint64). 예: 0x0000000200000009 → 화면 뱃지는 seq #9
assetSymbolstring기준 자산 심볼 — 모든 금액의 단위 라벨. 예: "USDC"
depositChainsnumber[]입금 가능한 체인 ID 목록(중복 제거·우선순위 순). 예: [49088, 11155111]. 2개 이상이면 체인 셀렉터 노출
chainsChainInfo[]depositChains와 같은 순서의 체인 메타 — { chainId, label, nativeCurrency }. 셀렉터 라벨·가스 통화 안내에 그대로 사용
tranches[]TrancheOverview[](트랜치 × 볼트 체인) 단위 배열 — 워터폴 우선순위 순(0번이 senior). 단일 체인 상품이면 2개

ChainInfo — chains[] 항목 필드

필드타입의미
chainIdnumber체인 ID. 예: 49088(Bifrost)·11155111(Sepolia)
labelstring표시 이름 — 체인 셀렉터·뱃지에 그대로. 예: "Bifrost"
nativeCurrencystring가스 통화 심볼 — INSUFFICIENT_GAS 문구에 사용. 예: Bifrost "BFC" · Sepolia "ETH"
rpcUrlstring | undefined이 체인 조회·tx에 쓸 RPC. create({ chains })로 오버라이드 — 조회 응답엔 노출 안 됨(내부용)
ichainsdepositChains같은 순서입니다 — depositChains[i]의 메타가 chains[i]. 셀렉터 라벨·가스 안내를 인덱스로 짝지어 쓸 수 있습니다. 체인 정의는 OMNIFI_CHAINS 레지스트리 정본이며 registerChains()로 확장합니다.

TrancheOverview — tranches[] 항목 필드

필드타입의미 · null 조건 · 예시
name'senior' | 'junior'트랜치 종류 — 화면 라벨·액션 파라미터로 그대로 사용
chainIdnumber이 항목 볼트의 체인. 예: 11155111(Sepolia)
aprPercentnumber | nullSenior 고정 이율(연 %). 예: 3 → "3.00% 고정". Junior는 null → "변동 — 잔여 수익"으로 표기
sharePricenumber | null최근 정산 확정 share 가격(기준 자산/share). 1.0 = 원금 기준, 예: 1.000069. toFixed(6) 권장. 첫 정산 전이면 null
shareSymbolstringshare 토큰 심볼. 예: "oSR"

Overview — 나머지 필드

필드타입의미 · null 조건 · 예시
tvlAmount | null운용 총액(상품 NAV, 정산 확정치·기준 자산 단위). 첫 정산 전이면 null → "기록 없음". formatted는 소수 2자리 절사
settlementRoundnumber최근 정산 회차 번호. 0 = 아직 정산 없음
settledAtDate | null최근 정산 기록 시각 — 가격·TVL 옆에 반드시 병기. 미정산이면 null
nextSettlementAtDate다음 정산 예정 시각(사이클 종료 시각). 실제 실행은 봇 트리거라 수 분 지연 가능
orderCloseAtDate이번 회차 신청 마감 시각 — 이후 신청은 다음 회차 배정. 카운트다운에 사용
settlementPeriodMinutesnumber정산 주기(분). 예: 60

예시 — 실제 응답

live · testbed
{
  productId: 8589934601,            // 0x0000000200000009 (시나리오 A) — 화면엔 seq #9로 표기
  assetSymbol: 'USDC',
  depositChains: [49088, 11155111],
  chains: [{ chainId: 49088, label: 'Bifrost', nativeCurrency: 'BFC' },
           { chainId: 11155111, label: 'Sepolia', nativeCurrency: 'ETH' }],
  tranches: [                        // (트랜치 × 볼트 체인) 4항목 — 앞 2개만 표시
    { name: 'senior', chainId: 49088,    aprPercent: 3,    sharePrice: 1.000069, shareSymbol: 'oSR' },
    { name: 'junior', chainId: 49088,    aprPercent: null, sharePrice: 1.000335, shareSymbol: 'oJR' }, /* … Sepolia 2개 */ ],
  tvl: { formatted: '2,300.25', symbol: 'USDC', raw: 2300254000n, decimals: 6 },
  settlementRound: 14,
  settledAt:        2026-08-21T03:52:45Z,  // "실시간 아님" 병기 기준 시각
  nextSettlementAt: 2026-08-25T03:44:38Z,
  orderCloseAt:     2026-08-25T03:24:38Z   // 마감 카운트다운용
}
sharePrice는 실시간이 아닙니다 — settledAt 병기가 규칙입니다 (핵심 개념 ④).
Data API overview()

overview() — product page in one call

Everything a product page needs: tranche structure, rates, prices, TVL, settlement schedule.

overview(): Promise<Overview>

No parameters · no wallet required · throws OmniFiError on failure

Return fields — full Overview

FieldTypeMeaning · null condition · example
productIdnumberHub ledger product identifier (uint64), e.g. 0x0000000200000009 — shown as seq #9
assetSymbolstringBase-asset symbol — the unit label for every amount, e.g. "USDC"
depositChainsnumber[]Chain IDs accepting deposits (deduped, priority order), e.g. [49088, 11155111]. Show a chain selector when > 1
chainsChainInfo[]Chain metadata aligned with depositChains{ chainId, label, nativeCurrency } for selector labels and gas guidance
tranches[]TrancheOverview[](tranche × vault chain) entries in waterfall order — index 0 is senior

ChainInfo — chains[] item fields

FieldTypeMeaning
chainIdnumberChain ID, e.g. 49088 (Bifrost) / 11155111 (Sepolia)
labelstringDisplay name for selectors/badges, e.g. "Bifrost"
nativeCurrencystringGas currency symbol for INSUFFICIENT_GAS messages — "BFC" / "ETH"
rpcUrlstring | undefinedRPC for this chain's reads/txs; override via create({ chains }) — internal, not surfaced in responses
ichains is index-aligned with depositChains (chains[i] describes depositChains[i]). Chain definitions live in the OMNIFI_CHAINS registry; extend via registerChains().

TrancheOverview — tranches[] item fields

FieldTypeMeaning · null · example
name'senior' | 'junior'Tranche type — usable directly as an action parameter
chainIdnumberChain of this entry's vault, e.g. 11155111 (Sepolia)
aprPercentnumber | nullSenior fixed APR (% p.a.), e.g. 3. null for Junior (variable/residual)
sharePricenumber | nullLatest settled share price (base asset per share); 1.0 = par, e.g. 1.000069. null before first settlement
shareSymbolstringShare token symbol, e.g. "oSR"

Overview — remaining fields

FieldTypeMeaning · null · example
tvlAmount | nullAUM (product NAV, as settled, in base asset). null before first settlement. formatted is floored to 2 dp
settlementRoundnumberLatest settlement round; 0 = none yet
settledAtDate | nullRecord time of the latest settlement — always display next to prices/TVL
nextSettlementAtDateNext settlement ETA (cycle end); actual execution is bot-triggered and may lag minutes
orderCloseAtDateOrder cutoff for this round — later requests roll to the next round
settlementPeriodMinutesnumberCycle length in minutes, e.g. 60
sharePrice is not a live quote — render settledAt next to it.

Example result — live testbed

live · testbed
{
  productId: 8589934601,            // 0x0000000200000009 (scenario A) — shown as seq #9 in UI
  assetSymbol: 'USDC',
  depositChains: [49088, 11155111],
  chains: [{ chainId: 49088, label: 'Bifrost', nativeCurrency: 'BFC' },
           { chainId: 11155111, label: 'Sepolia', nativeCurrency: 'ETH' }],
  tranches: [                        // (tranche × vault chain) — 4 entries, first 2 shown
    { name: 'senior', chainId: 49088,    aprPercent: 3,    sharePrice: 1.000069, shareSymbol: 'oSR' },
    { name: 'junior', chainId: 49088,    aprPercent: null, sharePrice: 1.000335, shareSymbol: 'oJR' }, /* … Sepolia 2 */ ],
  tvl: { formatted: '2,300.25', symbol: 'USDC', raw: 2300254000n, decimals: 6 },
  settlementRound: 14,
  settledAt:        2026-08-21T03:52:45Z,  // render this next to prices
  nextSettlementAt: 2026-08-25T03:44:38Z,
  orderCloseAt:     2026-08-25T03:24:38Z   // for the cutoff countdown
}
데이터 API myAccount()

myAccount() — 유저 대시보드 데이터 단일 조회

잔액·투자 자격·트랜치별 보유량과 진행 상태. 지갑 연결 없이 주소만으로 동작합니다.

myAccount(user: Address): Promise<MyAccount>

반환 필드 — MyAccount 전체

필드타입의미 · null 조건 · 예시
walletBalanceAmount기본 체인(첫 트랜치의 체인)의 지갑 자산 잔액. 예: formatted "1,350.6529". 단일 체인 상품은 이것으로 충분
walletBalances[]{ chainId, balance: Amount }[]체인별 지갑 잔액 — 멀티 볼트 상품의 체인 셀렉터 옆 잔액 표시용. 단일 체인이면 1개
canInvestboolean화이트리스트 자격 여부. false면 입금 UI 대신 온보딩 안내 — 사전 판별로 NOT_WHITELISTED 에러를 예방
tranches[]MyTranche[](트랜치 × 볼트 체인) 항목 — overview().tranches와 같은 순서·같은 인덱스
tranches[i].name'senior' | 'junior'트랜치 종류
tranches[i].chainIdnumber이 항목 볼트의 체인
tranches[i].sharesAmount지갑 보유 share (수령 대기분 미포함 — 수령 대기분은 redeem이 아니라 deposit.amount가 receivable일 때 표시)
tranches[i].depositActionState입금 방향 진행 상태 — 아래 ActionState 명세
tranches[i].redeemActionState상환 방향 진행 상태

ActionState 필드 명세

필드타입의미 · null 조건 · 예시
status'none' | 'processing' | 'receivable'요청 상태 — 화면 분기의 기준값. none = 진행 중 요청 없음
statusLabelstring | null상태 한국어 표준 라벨: processing → "정산 대기", receivable → "수령 가능". none이면 null. 메인 위젯·CTA는 이 라벨만 사용
stageCodestring | null진행 단계 코드(상세): depositRequest·bridging·queued·settlement·shareReceivable… none이면 null
stageLabelstring | null단계 표준어: 입금 bridging → "자금 공급 중", 상환 → "브릿징" 등. 상세 뷰 전용 — 메인에 노출하지 않음
simpleStep1 | 2 | 3 | null간소화 3단계 위치: 1 신청 완료 · 2 정산 대기 · 3 수령 가능. 위젯 하단 스텝 칩용
steps[]{ code, label, state }[]전체 단계 타임라인(6칸, 문서 순서 고정). state: 'done' | 'current' | 'upcoming' — 프로그레스 바에 그대로
amountAmount | nullprocessing = 신청량(입금이면 자산·상환이면 share), receivable = 수령 가능량(입금이면 share·상환이면 자산). symbol이 단위를 반영. none이면 null

ActionState — 상태와 단계

진행 상태는 요청 상태진행 단계 두 가지로 제공됩니다. 메인 위젯은 ① 요청 상태만으로 구성하고, ② 진행 단계는 상세 뷰에서만 씁니다. 둘을 한 화면에 섞으면 상태 표시가 일관되지 않습니다.

구분필드사용처
① 요청 상태 (요약)status · statusLabelnone processing("정산 대기") receivable("수령 가능")메인 위젯·CTA
② 진행 단계 (상세)stageCode · stageLabel · steps[]아래 단계 표상세 뷰·프로그레스 바
간소화 3단계simpleStep1 신청 완료 · 2 정산 대기 · 3 수령 가능위젯 스텝 칩
i브릿징은 유저를 차단하는 단계가 아닙니다 — processing 동안 메인 표시는 항상 "정산 대기"이며, "자금 공급 중" 등 세부 단계는 상세 뷰에만 노출합니다.

진행 단계 전체 표 — steps[]의 순서

입금 (deposit)

stageCodestageLabel비고
depositRequest입금 신청 완료유저 tx — 이 시점에 입금액 확정
bridging자금 공급 중자동 · 상세 뷰 전용 — "브릿지 대기 중" 문구 금지
queued정산 대기Pending 기본 표시 · 다음 정산 예정 시각 병기
settlement정산 확정share 수량이 여기서 확정
shareReceivable수령 가능receive() 호출 가능
shareReceived수령 완료수령 후 목록에서 제거

상환 (redeem)

stageCodestageLabel비고
redeemRequest상환 신청 완료유저 tx — 취소 불가 고지는 신청 전에
bridging브릿징자동 · 상세 뷰 전용
queued정산 대기Pending 기본 표시
settlement정산 확정지급액 확정
collateralReceivable수령 가능지급 자산 수령 대기
collateralReceived수령 완료

amount: processing이면 신청량, receivable이면 수령 가능량 — symbol이 단위를 반영합니다.

결과 예시

live
{
  canInvest: true,                   // false면 입금 버튼 대신 온보딩 안내
  walletBalances: [
    { chainId: 49088,    balance: { formatted: '0',     symbol: 'USDC' } },
    { chainId: 11155111, balance: { formatted: '9,600', symbol: 'USDC' } } ],
  tranches: [                        // (트랜치 × 체인) — overview().tranches와 같은 인덱스
    { name: 'senior', chainId: 49088,
      shares: { formatted: '0', symbol: 'oSR' },
      deposit: { status: 'none', statusLabel: null, steps: [], amount: null },
      redeem:  { status: 'none' } }, /* … 3항목 더 */ ]
}
Data API myAccount()

myAccount() — user dashboard in one call

Balance, eligibility, per-tranche holdings and progress. Works with just an address.

myAccount(user: Address): Promise<MyAccount>

Return fields — full MyAccount

FieldTypeMeaning · null condition · example
walletBalanceAmountWallet asset balance on the default chain (first tranche's chain), e.g. formatted "1,350.6529"
walletBalances[]{ chainId, balance: Amount }[]Per-chain wallet balances — for the chain selector on multi-vault products
canInvestbooleanWhitelist eligibility; false → show onboarding instead of the deposit form
tranches[]MyTranche[](tranche × vault chain) entries — same order/index as overview().tranches
tranches[i].chainIdnumberChain of this entry's vault
tranches[i].sharesAmountShares held in the wallet (excludes unreceived finalized shares — those appear as deposit.amount when receivable)
tranches[i].deposit / .redeemActionStatePer-direction progress — spec below

ActionState field spec

FieldTypeMeaning · null condition
status'none' | 'processing' | 'receivable'Request status — the branching key. none = no request in flight
statusLabelstring | nullStatus label ("awaiting settlement" / "receivable" in Korean). Drive the main widget/CTA with this only; null when none
stageCodestring | nullProcess-stage code (detailed): depositRequest · bridging · queued · settlement · shareReceivable
stageLabelstring | nullStage label ("funds being deployed" etc.) — detail views only
simpleStep1 | 2 | 3 | nullSimplified position: 1 requested · 2 awaiting settlement · 3 receivable
steps[]{ code, label, state }[]Full 6-step timeline in fixed order; state: 'done' | 'current' | 'upcoming' — feed straight into a progress bar
amountAmount | nullRequested amount while processing (asset for deposits, shares for redeems); receivable amount once receivable (shares for deposits, asset for redeems)

ActionState — status and stage

Progress comes in two forms: a coarse request status and a detailed process stage. Drive the main widget from the request status only, and keep the process stage to detail views. Using both in one view makes the displayed state inconsistent.

FormFieldsValuesWhere
① Request status (summary)status · statusLabelnone processing receivableMain widget · CTA
② Process stage (detailed)stageCode · stageLabel · steps[]deposit: depositRequest → bridging → queued → settlement → shareReceivable → shareReceived (redeem analogous)Detail view · progress bar
Simplified 3-stepsimpleStep1 requested · 2 awaiting settlement · 3 receivableWidget step chips
iBridging never blocks the user — during processing the main label is always "awaiting settlement"; sub-stages belong to detail views.

steps[] carries the full sequence with state: 'done' | 'current' | 'upcoming' per entry — feed it straight into a progress bar. amount is the requested amount while processing and the receivable amount once receivable.

Example result

live
{
  canInvest: true,                   // false → show onboarding instead of the deposit button
  walletBalances: [
    { chainId: 49088,    balance: { formatted: '0',     symbol: 'USDC' } },
    { chainId: 11155111, balance: { formatted: '9,600', symbol: 'USDC' } } ],
  tranches: [                        // (tranche × chain) — same index as overview().tranches
    { name: 'senior', chainId: 49088,
      shares: { formatted: '0', symbol: 'oSR' },
      deposit: { status: 'none', statusLabel: null, steps: [], amount: null },
      redeem:  { status: 'none' } }, /* … 3 more */ ]
}
데이터 API activity()

activity() — 크로스체인 진행 타임라인

진행 중인 요청이 지금 어느 단계에 있는지, 단계 타임라인으로 보여줄 데이터를 반환합니다.

activity(user: Address): Promise<ActivityItem[]>

빈 배열 = 진행 중 요청 없음(정상). 완료된 요청은 자동으로 목록에서 제외됩니다.

반환 필드 — ActivityItem

필드타입화면 용도
requestIdHexdeposit()/redeem() 반환값과 연결 — 목록 키
kind'deposit' | 'redeem'입금 / 상환 — 카드 제목·아이콘
tranche'senior' | 'junior'트랜치 종류 — 카드 제목("Senior 입금")
chainIdnumber신청이 발생한 볼트 체인 — 멀티 볼트 상품에서 체인 병기
amountAmount신청 금액 (입금 = 자산 단위 · 상환 = share 단위)
phasestring국면 뱃지 — "자금 공급 중"(입금)·"브릿징"(상환)·"정산 대기"·"정산 확정"·"수령 가능"
stepsTimelineStep[]진행 칩: "신청 완료 ✓ › 브릿징 › 허브 도착" — 순서 보장 (아래 TimelineStep 참조)
adapterLegs{ chainId: number, steps: TimelineStep[] }[]수익원 배분 진행 (체인별 · 상세 뷰 전용)
settlementRoundnumber | null배정 정산 회차 — 배정 전이면 null
idone: false는 "미도달"이며 "해당 없음"이 아닙니다 — 해당 없는 단계는 배열에 포함되지 않습니다.

결과 예시 — 형태

live
[{
  requestId: '0x000000020000000200…',  // 화면엔 seq 축약 표기 권장
  kind: 'deposit', tranche: 'senior', chainId: 11155111,
  amount: { formatted: '100', symbol: 'USDC' },
  phase: 'supplying funds',
  steps: [
    { label: 'requested',  done: true,  txHash: '0xce87d8…', chainId: 11155111, at: 2026-08-19T02:00Z },
    { label: 'bridging',   done: true,  txHash: '0x9a3e39…', chainId: 11155111, at: 2026-08-19T02:01Z },
    { label: 'at hub',     done: false, txHash: null, chainId: null, at: null } ],
  adapterLegs: [{ chainId: 49088, steps: [ /* yield-source legs */ ] }],
  settlementRound: null                // 회차 배정 전
}]
// ※ 단계·tx는 TxRegistry 기록(txRecorder attestation) — 미적재 환경이면 steps가 비어있을 수 있음

TimelineStep 필드 — 단계 1개의 형태

필드타입화면에서
labelstring표준어 라벨 — 신청 완료 · 브릿징 · 허브 도착 · 수익원 전달 · 공급 반영 · 처리 완료
doneboolean도달 ✓ — 미도달 단계는 회색, 첫 미도달을 파란 current로 강조 권장
txHash · chainIdHex | null · number | null이 단계를 기록한 tx와 실행 체인 — 탐색기 링크 (Sepolia는 Etherscan)
atDate | null허브 원장 기록 시각 — 단계 경과 표시
failed · attemptCountboolean? · number?브릿지 단계 전용 — 최근 시도가 CCCP 롤백(Reverted)이면 failed, 이때 txHash는 롤백된 시도 tx. 빨간 "↻ 재시도 대기" 표시 권장
Data API activity()

activity() — cross-chain progress timeline

Data for rendering where each in-flight request currently is, as a step timeline.

activity(user: Address): Promise<ActivityItem[]>

Empty array = nothing in flight (normal). Completed requests drop off automatically.

FieldTypeMeaning
requestIdHexJoins with deposit()/redeem() return; use as the list key
kind'deposit' | 'redeem'Deposit / redeem — card title, icon
tranche'senior' | 'junior'Tranche type — card title ("Senior deposit")
chainIdnumberVault chain the request originated on
amountAmountRequested amount (asset units for deposits, shares for redeems)
phasestringPhase badge (standardized Korean labels)
stepsTimelineStep[]Progress chips, order guaranteed (see TimelineStep below)
adapterLegs{ chainId: number, steps: TimelineStep[] }[]Yield-source allocation legs (per chain, detail view)
settlementRoundnumber | nullAssigned round; null before assignment
idone: false means "not yet", not "not applicable" — inapplicable steps are absent from the array.

Example shape

live
[{
  requestId: '0x000000020000000200…',  // show the seq suffix in the UI, not the full id
  kind: 'deposit', tranche: 'senior', chainId: 11155111,
  amount: { formatted: '100', symbol: 'USDC' },
  phase: 'supplying funds',
  steps: [
    { label: 'requested',  done: true,  txHash: '0xce87d8…', chainId: 11155111, at: 2026-08-19T02:00Z },
    { label: 'bridging',   done: true,  txHash: '0x9a3e39…', chainId: 11155111, at: 2026-08-19T02:01Z },
    { label: 'at hub',     done: false, txHash: null, chainId: null, at: null } ],
  adapterLegs: [{ chainId: 49088, steps: [ /* yield-source legs */ ] }],
  settlementRound: null                // before a round is assigned
}]
// ※ steps/tx come from TxRegistry (txRecorder attestation) — may be empty where the recorder has not attested
데이터 API priceHistory()

priceHistory() — 차트 데이터

회차별 확정 가격과 TVL을 반환합니다. 모든 값이 number 타입이므로 차트 라이브러리에 직접 전달할 수 있습니다.

priceHistory(): Promise<PricePoint[]>
응답 (테스트베드 라이브)
[
  { "round": 1, "at": "2026-08-12T06:34:27Z", "senior": 1.0000047, "junior": 0.9996873, "tvl": 1199.94 },
  { "round": 2, "at": "2026-08-12T07:16:33Z", "senior": 1.0000171, "junior": 0.9997577, "tvl": 1399.97 }
]
iJunior 표시용 APR (온체인 고정 이율이 없는 잔여 스프레드 트랜치): lastPeriodAprPercent(series)직전→현재 정산 NAV 변화만 1년 환산합니다. 표시 정책: 음수(구간 손실)면 +0.00%로 클램프. 전 구간 성장률 연환산은 realizedApyPercent, 연환산 없는 구간 수익률은 lastPeriodReturnPercent — 셋 다 export. 정산 2회 미만이면 null.
i재적재 시점: overview().settlementRound 변경 시에만 — 정산 사이에는 값이 변하지 않습니다.

결과 예시 — 테스트베드 라이브

live
[ …,
  { round: 8, at: 2026-08-19T15:02Z, senior: 1.000088, junior: 1.000000, tvl: 350.01 },
  { round: 9, at: 2026-08-20T03:33Z, senior: 1.000131, junior: 1.000000, tvl: 350.03 } ]
// 전부 number — 차트 라이브러리에 그대로. senior만 오르는 중 = 고정 이율 누적, junior는 수익원 미가동
Data API priceHistory()

priceHistory() — chart data

Per-round finalized prices and TVL, all plain numbers.

priceHistory(): Promise<PricePoint[]>
FieldTypeMeaning · example
roundnumberSettlement round — default X axis, e.g. 2
atDate | nullActual record time for tooltips/labels; null on legacy ledgers without timestamps
senior / juniornumberFinalized share prices, e.g. 1.0000171 / 0.9997577
tvlnumberAUM at that round in base-asset units, e.g. 1399.97
iDisplay APR for junior (no fixed on-chain rate — residual spread): lastPeriodAprPercent(series) annualises only the latest settlement-to-settlement NAV change. Display policy: clamp negatives (period loss) to +0.00%. Whole-series CAGR: realizedApyPercent; non-annualised period return: lastPeriodReturnPercent — all three exported. null under two settlements.
iRefetch only when overview().settlementRound changes.

Example result — live testbed

live
[ …,
  { round: 8, at: 2026-08-19T15:02Z, senior: 1.000088, junior: 1.000000, tvl: 350.01 },
  { round: 9, at: 2026-08-20T03:33Z, senior: 1.000131, junior: 1.000000, tvl: 350.03 } ]
// all number — feed straight to a chart. senior rising = fixed APR accruing; junior flat = yield source idle
데이터 API investmentHistory()

investmentHistory() — 유저 입출금 내역

"내 입출금 내역" 화면용 히스토리 API — 인덱서 없이 온체인 직조회로 파생됩니다.

investmentHistory(user, { withSteps? }): Promise<InvestmentRecord[]>
ts
const fls = await omnifi.investmentHistory(userAddress)   // 최신순 — 지갑 연결 불필요
// [{ kind: 'deposit', tranche: 'senior', amount: 100 USDC → received: 99.9956 oSR,
//    round: 2, at: Date, status: 'approved' }, …]

반환 필드 — InvestmentRecord

필드타입화면에서
kind'deposit' | 'redeem'행 아이콘·라벨 (입금/상환)
tranche'senior' | 'junior'트랜치 뱃지
amountAmount신청 금액 — 입금은 기준 자산, 상환은 share
receivedAmount | null확정 수령분 — 입금은 share, 상환은 기준 자산. 미승인이면 null → "정산 대기" 표기
roundnumber | null확정(승인) 회차 — 내역 정렬 기준. 미승인이면 null
atDate | null확정 회차의 원장 기록 시각 — 날짜 표기 기준. 미승인이면 null
status'pending' | 'approved'대기/확정 뱃지
chainIdnumber신청 볼트 체인 — 탐색기 링크 분기

withSteps 옵션 시 추가 필드

investmentHistory(user, { withSteps: true })일 때만 채워집니다 — 요청 처리 과정 타임라인.

필드타입화면에서
stepsTimelineStep[]요청 처리 단계 (신청 완료 → 브릿징 → 허브 도착 …) — 단계별 tx·시각. TimelineStep 참조
adapterLegs{ chainId: number, steps: TimelineStep[] }[]체인별 수익원 leg (입금=공급 · 상환=회수) 진행
settlementSettlementSection | null배정 회차의 정산 사이클 — { round, settleStarted, chains }. 정산 개시 tx + 체인별 NAV 수집→확정 반영 단계 (settlementStatus와 동형)
receiveStepTimelineStep수령 단계 — 수령 이력에서 귀속. done이면 여정 100%(txHash = 실제 수령 tx), 매칭 시 phase도 '수령 완료'
phasestring | null현재 국면 — 자금 공급 중 · 정산 대기 · 정산 진행 중 · 정산 확정 · 수령 가능 · 수령 완료

withSteps — 요청별 처리 과정 타임라인

{ withSteps: true }를 주면 각 이력에 TxRegistry의 과정 기록이 합쳐집니다 — steps[](신청 완료→브릿징→허브 도착→…, 단계별 txHash·chainId·허브 기록 시각 at), adapterLegs[](체인별 수익원 전달), phase. 레코더 가동 전에 처리된 요청은 빈 배열입니다. 과거 입금·상환의 전 과정을 시간대별 tx와 함께 보여주는 화면이 이 옵션 하나로 끝납니다.

receiveHistory() — 수령 기록

receiveHistory(user, limit?): Promise<ReceiveRecord[]>

수령(receive) tx 이력 — 최신순. 수령은 요청과 1:1로 묶이지 않는 풀링 구조라 별도 조회입니다 (표시 목적이라면 withStepsreceiveStep 귀속으로 충분한 경우가 많습니다).

필드타입화면에서
txHash · chainIdHex · number수령 tx — 탐색기 링크
tranche · kindTrancheName · RequestKind어느 트랜치의 입금분/상환분 수령인지
amountAmount수령분 — 입금 수령은 share, 상환 수령은 기준 자산
receiverAddress실제 수취 주소 — 요청자와 다를 수 있음(수령처 지정)
atDate | null허브 기록 시각

정산 사이클 · 수령 기록까지 — 전 과정 공개

withSteps 결과의 settlement 필드가 배정 회차의 정산 사이클 전 과정을 담습니다 — 정산 개시(trigger tx) → 체인별 NAV 수집 전달 → NAV 수집 → NAV 회신 → NAV 확정 → 확정 반영 → 정산 완료, 단계마다 tx·허브 기록 시각. 유저가 "정산 대기"에서 "정산 확정"으로 넘어가는 동안 시스템이 실제로 무엇을 했는지 하나하나 검증할 수 있습니다. 수령(receive) tx는 receiveHistory(user)로 별도 조회 — { txHash, tranche, chainId, receiver, amount, kind, at } (요청과 1:1로 안 묶이는 풀링 수령이라 분리).

데이터 원천

허브 Investments 원장을 requestId(seq) 순회로 재구성합니다 — 이벤트·인덱서·TxRegistry를 쓰지 않아 어떤 환경에서도 동작합니다.

신청 "제출 시각"은 팔렛에 저장되지 않아 확정 회차 시각(at)으로 대표합니다. 지갑 간 share 이전(transfer)은 원장 요청이 아니라 내역에 나오지 않습니다.
i갱신 주기: overview().settlementRound 변경 시에만 재적재 (폴링 전략).

결과 예시 — 테스트베드 라이브 (실지갑 여정)

live
[
  { kind: 'deposit', tranche: 'senior', status: 'pending',   // 방금 신청 — 정산 대기
    amount: { formatted: '100', symbol: 'USDC' }, received: null, round: null, at: null },
  { kind: 'redeem',  tranche: 'senior', status: 'approved',
    amount:   { formatted: '199.9908', symbol: 'oSR' },
    received: { formatted: '200.0005', symbol: 'USDC' },     // 원금 200 + 이자
    round: 6, at: 2026-08-19T03:27Z },
  { kind: 'deposit', tranche: 'senior', status: 'approved',
    amount:   { formatted: '100', symbol: 'USDC' },
    received: { formatted: '99.9952', symbol: 'oSR' },        // 확정가 1.000048로 발행
    round: 5, at: 2026-08-19T03:10Z } ]
Data API investmentHistory()

investmentHistory() — user deposit/redeem history

Powers the "my transactions" screen — derived entirely from on-chain reads, no indexer.

investmentHistory(user, { withSteps? }): Promise<InvestmentRecord[]>

Newest first. Each entry: kind (deposit/redeem), tranche, amount (requested — asset for deposits, shares for redeems), received (confirmed — shares for deposits, asset for redeems; null while pending), round/at (settlement round and its ledger time), status.

Request submission time is not stored on-chain — the settlement round's time stands in. Wallet-to-wallet share transfers are not ledger requests and do not appear here.

Example result — live testbed

live
[
  { kind: 'deposit', tranche: 'senior', status: 'pending',   // just requested — awaiting settlement
    amount: { formatted: '100', symbol: 'USDC' }, received: null, round: null, at: null },
  { kind: 'redeem',  tranche: 'senior', status: 'approved',
    amount:   { formatted: '199.9908', symbol: 'oSR' },
    received: { formatted: '200.0005', symbol: 'USDC' },     // principal 200 + yield
    round: 6, at: 2026-08-19T03:27Z },
  { kind: 'deposit', tranche: 'senior', status: 'approved',
    amount:   { formatted: '100', symbol: 'USDC' },
    received: { formatted: '99.9952', symbol: 'oSR' },        // minted at settled price 1.000048
    round: 5, at: 2026-08-19T03:10Z } ]
데이터 API profitHistory()

profitHistory() — 기간 손익 (일·주·월)

"내 수익 리포트" 화면용 — 원금 대비 기간별 손익·수익률을 온체인 직조회만으로 계산합니다.

profitHistory(user, { interval? }): Promise<ProfitPoint[]>
ts
const monthly = await omnifi.profitHistory(userAddress, { interval: 'month' })  // 'day' | 'week' | 'month'
// [{ period: '2026-08', profit: 0.0005 USDC, returnPct: 0.02,
//    startValue → endValue, byTranche: { senior, junior } }]

반환 필드 — ProfitPoint

필드타입화면에서
periodstring'2026-08'(month) · '2026-08-19'(day) · '2026-W34'(week) — X축 라벨
profitAmount기간 손익 (기준 자산) — 리포트 카드 메인 숫자
returnPctnumber | null기간 수익률 % (기간 시작 평가액 대비) — 시작 보유 0이면 null → "신규 진입"
startValue · endValueAmount기간 시작·종료 평가액
byTranche{ senior, junior }손익 분해 (기준 자산 number) — 스택 차트용

계산 원리

  • 회차별 보유 share × 확정가 변동을 기간 버킷으로 적산 — 보유량은 investmentHistory() 이력에서 재구성, 가격·시각은 회차 원장(priceHistory와 동일 원천).
  • 손익은 정산 확정가 기준(실현 기준) — 미정산 구간의 추정 수익은 포함하지 않습니다.
지갑 간 share 이전(transfer)은 원장 요청이 아니라 손익 계산에 반영되지 않습니다 — 입출금이 전부 이 상품 요청이라는 전제입니다.
i갱신 주기: overview().settlementRound 변경 시에만 재적재 (폴링 전략).

결과 예시 — 테스트베드 라이브 (입금 200 → 전량 상환 여정)

live
[{
  period: '2026-08',
  from: 2026-08-18T13:19Z, to: 2026-08-20T03:33Z,
  profit: { formatted: '0.0005', symbol: 'USDC' },  // 200 USDC를 몇 시간 보유한 senior 이자
  returnPct: null,                                    // 기간 시작 보유 0 → "신규 진입" 표기
  startValue: { formatted: '0' }, endValue: { formatted: '0' },  // 기간 내 전량 상환으로 기말 0
  byTranche: { senior: 0.000598, junior: 0 }
}]
Data API profitHistory()

profitHistory() — periodic P&L (day · week · month)

Powers the "my profit report" screen — profit vs principal per period, from on-chain reads only.

profitHistory(user, { interval?: 'day' | 'week' | 'month' }): Promise<ProfitPoint[]>

Accrues per-round held shares × settled-price change into period buckets — holdings are reconstructed from investmentHistory(). Each point: period label, profit (base asset), returnPct (vs period-start value; null when starting from zero), startValue/endValue, byTranche breakdown. P&L is realized (settled prices only).

Wallet-to-wallet share transfers are not ledger requests and are excluded from P&L.
iReload only when overview().settlementRound changes.

Example result — live testbed

live
[{
  period: '2026-08',
  from: 2026-08-18T13:19Z, to: 2026-08-20T03:33Z,
  profit: { formatted: '0.0005', symbol: 'USDC' },  // senior yield on 200 USDC held for a few hours
  returnPct: null,                                    // zero holding at period start → mark as "new entry"
  startValue: { formatted: '0' }, endValue: { formatted: '0' },  // fully redeemed within the period → ends at 0
  byTranche: { senior: 0.000598, junior: 0 }
}]
데이터 API allocation()

allocation() — 포트폴리오 구성

상품의 자금이 체인별·수익원별로 어떤 비중으로 배분되는지 반환합니다. 구성 차트의 데이터 소스입니다.

allocation(): Promise<AllocationInfo>
필드타입화면에서
chains[]{ chainId, label, weightPercent, sources[] }체인별 배분 비중 도넛/바 차트 — sources는 체인 내 수익원별 서브 비중(onchain/offchain 구분)
valuationsSourceValuation[] | null최신 정산 기준 수익원 실평가 — 상세는 sourceValuations(). 미기록이면 null
roundnumber | null실평가 기준 회차 — "정산 #N 기준" 병기

결과 예시 — 테스트베드 라이브

live
{
  chains: [ { chainId: 11155111, label: 'Sepolia', weightPercent: 40, sources: [{ type: 'onchain', weightPercent: 100 }] },
            { chainId: 49088,    label: 'Bifrost', weightPercent: 60, sources: [{ type: 'onchain', weightPercent: 100 }] } ],
  valuations: [ { chainId: 49088, principal: { formatted: '1,379.99', symbol: 'USDC' }, totalUsd: 1380.15, … },
                { chainId: 11155111, principal: { formatted: '919.99', symbol: 'USDC' }, totalUsd: 920.10, … } ],
  round: 14
}
Data API allocation()

allocation() — portfolio composition

How the product allocates capital across chains and yield sources — for composition charts.

allocation(): Promise<AllocationInfo>

chains[] — per-chain weight (weightPercent) with nested per-source weights (onchain/offchain). valuations/round — latest settled valuation snapshot (see sourceValuations()); null before the first record.

데이터 API basketHoldings()

basketHoldings() — 바스켓 구성 종목

바스켓형(ETF형) 상품의 구성 종목·현재가·평가액·목표 비중을 조회합니다. 시나리오 D(로빈후드 QQQ 미러링 8종목 바스켓) 전용 — 예치형 상품(A·B·C)은 빈 배열을 반환합니다.

ts
const holdings = await omnifi.basketHoldings(46630)
// [{ symbol: 'mNVDA', amount: 0.8098, priceUsd: 219.91, valueUsd: 178.09, weightPercent: 20.2 },
//  { symbol: 'mAAPL', amount: 0.4652, priceUsd: 317.48, valueUsd: 147.68, weightPercent: 16.92 }, … 8종]

BasketHolding

필드타입의미
symbolstring종목 심볼. 예: "mTSLA"
addressAddress종목 토큰 주소 (스포크 체인)
amountnumber어댑터 보유 수량 (종목 단위)
priceUsdnumber1 종목 = ? USDC — 현재 Uniswap V3 풀가
valueUsdnumber평가액 (USDC) = amount × priceUsd
weightPercentnumber목표 비중 % — 실제 비중은 valueUsd/합계로 계산
i현재 상태 스냅샷입니다. 종목별 가격 시계열은 basketPriceHistory(chainId)로 — v3 어댑터부터 정산마다 종목별 priceUsd가 프리컴파일에 기록되어, 인덱서 없이 회차별 가격 차트를 그릴 수 있습니다 (반환: { symbol, address, points: [{ round, at, priceUsd }] }[]).

인자 chainId는 바스켓 어댑터가 있는 스포크 체인(시나리오 D는 46630). 스포크 RPC 미설정·바스켓 없음이면 [].

Data API basketHoldings()

basketHoldings() — basket constituents

Constituents, current prices, values and target weights for basket-type (ETF-like) products. Scenario D (Robinhood QQQ-mirroring basket) only — deposit-type products (A·B·C) return an empty array.

ts
const holdings = await omnifi.basketHoldings(46630)
// [{ symbol: 'mNVDA', amount: 0.8098, priceUsd: 219.91, valueUsd: 178.09, weightPercent: 20.2 }, … 8 entries]
FieldTypeMeaning
symbol · addressstring · AddressConstituent token on the spoke chain
amountnumberAdapter holdings (token units)
priceUsdnumberCurrent Uniswap V3 pool price (USDC per token)
valueUsdnumberamount × priceUsd
weightPercentnumberTarget weight %; derive the actual weight from valueUsd/total
iPoint-in-time snapshot. For time series use basketPriceHistory(chainId) — since the v3 adapter, per-constituent priceUsd is recorded at every settlement, so round-by-round price charts need no indexer.
데이터 API custom flows

custom flow 조회 — 리워드 클레임 등

governance가 등록한 custom flow(예: 리워드 풀 클레임)의 진행/완료 타임라인을 조회합니다. 싱글체인·멀티체인 공통이며 조회는 전부 허브 프리컴파일 CustomFlows(0x…0204)입니다.

메서드 4종

메서드반환용도
flowDescriptor(flowId){ version, mainChainId, investorScoped, mainSlots, subTracks } | nullflow의 기대 토폴로지(어느 체인·어떤 슬롯). 미등록이면 null. 캐시 가능
activeFlows(user, flowId)instance_key[]진행중 목록 — 개시 즉시 close되는 flow(리워드 클레임)는 여기 안 남음
flowHistory(user, flowId, offset?, limit?){ instanceKeys, total }완료 내역, 최신순 페이지네이션 (limit ≤ 50 — 초과는 revert)
flowInstance(flowId, instanceKey){ investor, closed, pendingLanes, openedAt, mainLane, subTracks } | null실행 1건의 전체 타임라인. 미존재면 null

리워드 클레임 전용 고수준 API(rewardClaims() 등)는 리워드 페이지로 분리되어 있습니다 — 이 페이지는 범용 flow 조회만 다룹니다.

flowId는 bytes16 슬러그 — FLOW_IDS 상수를 사용합니다 (현재 FLOW_IDS.rewardClaim 1종). 멀티체인은 omnifi.flowHistory(user, FLOW_IDS.rewardClaim)처럼 파사드에서 바로, 싱글체인 TrancheSDK는 flowId 생략 시 reward-claim이 기본값입니다.

예시 — flow 이력 → 상세

ts
const { instanceKeys, total } = await sdk.flowHistory(me, FLOW_IDS.rewardClaim)
const inst = await sdk.flowInstance(FLOW_IDS.rewardClaim, instanceKeys[0])
// inst.mainLane[0].attempts[…].tx — 단계별 tx 증거 · slot_metadata는 (flow, slot) 스키마로 디코딩

규약

항목규칙
미존재 처리revert가 아니라 sentinel — descriptor 미등록 null · instance 미존재 null · history/active는 빈 배열. TxRegistry(get_request는 revert)와 다릅니다
recorded_at허브 블록번호(시각 아님) — 정렬용으로만 쓰고, 시각 표시는 tx_hash로 해당 체인 탐색기 조회
slot_metadataopaque bytes — (flow, slot)별 스키마로 디코딩. reward-claim slot 0 = uint256 amount
완료 판정closed(팔렛 계산값) 기준. 진행도 근사는 pendingLanes(0이면 완료)
i진행중 UI가 필요한 다단계 flow는 flowDescriptor(기대치)와 flowInstance(실제 기록)를 대조합니다 — 기록 배열에 없는 슬롯은 "미도달"이 아니라 descriptor에 있는지로 구분합니다. 리워드 클레임(1-slot·즉시 close)은 closed만 보면 충분합니다.
Data API custom flows

Custom flow reads — reward claims etc.

Timelines for governance-registered custom flows (e.g. reward-pool claims). Same surface for single-chain and multichain products; every read hits the hub CustomFlows(0x…0204) precompile.

MethodReturnsUse
flowDescriptor(flowId)topology | nullExpected chains/slots; null if unregistered. Cacheable
activeFlows(user, flowId)instance_key[]In-flight list — instant-close flows (reward claim) never appear here
flowHistory(user, flowId, offset?, limit?){ instanceKeys, total }Completed, most-recent first (limit ≤ 50 — reverts above)
flowInstance(flowId, instanceKey)timeline | nullOne execution's full timeline; null if absent

Reward-specific helpers (rewardClaims() etc.) live on the Rewards page — this page covers the generic flow reads only.

flowId is a bytes16 slug — use the FLOW_IDS constants (currently FLOW_IDS.rewardClaim). Absence is signalled by sentinels, never reverts (unlike TxRegistry's get_request): unregistered descriptor → null, missing instance → null, empty history → empty array. recorded_at is a hub block number, not a timestamp — sort with it, but resolve display times via tx_hash on the source chain.

데이터 API 리워드

리워드 — 조회·클레임·이력

RewardPool 애드온이 배선된 상품(현재 시나리오 B)의 보너스 이자. 예치 자산과 다른 통화일 수 있습니다 — B는 JPYC 예치·USDC 리워드. 적립은 정산·유저 tx마다 자동(harvest), 수령은 유저가 직접 클레임합니다.

메서드 3종 (TrancheSDK · 싱글체인)

메서드반환용도
rewardSupported(){ symbol, decimals } | null이 상품의 리워드 애드온 지원 여부 — 지갑 불필요·캐시. 카드 골격을 즉시 그릴 때
rewardClaimable(user){ raw, formatted, symbol, decimals } | null지금 클레임하면 받는 값 — 동기화된 claimable + 미동기(pending)분 합산. 미지원 상품은 null
claimReward(tranche?)Hash클레임 실행 (유저 tx — vault.claimReward). 수령액 0이면 revert
rewardClaims(user, { offset?, limit? }){ total, claims[] }클레임 이력 — custom flows(0x…0204) 기록. amount(slot 0 디코딩)·txHash·시각(at)
ts
const r = await sdk.rewardClaimable(me)      // { formatted: '261.876884', symbol: 'USDC', … } | null
await sdk.claimReward()                       // 유저 tx — 이후 이력은 recorder가 적재
const { claims } = await sdk.rewardClaims(me) // [{ amount, txHash, at, … }]

동작 규약

항목내용
적립 시점share를 보유한 상태에서 harvest 틱이 지나야 쌓입니다. 수령(mint) 시점의 lane부터 시작 — 방금 받았다면 다음 틱부터
pending 합산온체인 claimable은 share 이동/클레임 시점에만 동기화(lazy) — SDK가 lane 차이 × 보유 share 가치로 미동기분을 계산해 합산합니다
표시 정밀도formatted는 절사 없이 리워드 토큰 정밀도 전체(USDC 6자리) — 소액 드립도 보이게
손익 연동profitHistory()rewards 필드에 기간별 클레임 합이 붙습니다 — 통화가 달라 profit엔 합산하지 않음
이력 시각at은 허브 attestation 블록의 timestamp — 클레임 tx 시각과 수초 이내 근사
i클레임 이력의 저수준 원본은 custom flowsreward-claim flow — rewardClaims()는 그 위의 디코딩 편의 계층입니다.
Data API Rewards

Rewards — balance, claim, history

Bonus yield for products with the RewardPool add-on (currently scenario B). The reward asset can differ from the deposit asset — B deposits JPYC and rewards USDC.

MethodReturnsUse
rewardSupported()meta | nullDoes this product have the add-on — no wallet needed, cached
rewardClaimable(user)amount | nullWhat a claim would pay right now — synced claimable + un-synced pending
claimReward(tranche?)HashExecute the claim (user tx); reverts on zero
rewardClaims(user, opts?){ total, claims[] }Claim history from custom flows — amount, txHash, timestamp

Rewards accrue only while holding shares across harvest ticks. On-chain claimable is lazily synced — the SDK adds the pending portion (lane delta × share value). profitHistory() attaches per-period claimed rewards as a separate rewards field (different currency — never summed into profit).

데이터 API 수익원

수익원 — 어느 프로토콜에 얼마씩

상품이 지금 어느 수익원 프로토콜에 자금을 배치 중인지와 어댑터별 배분을 반환합니다. 각 어댑터의 name()(프로토콜 식별자)·평가액·비중을 한 번에 — 상품 상세의 "구성 수익원" 표에 그대로 씁니다.

yieldSources()

ts
const sources = await sdk.yieldSources()
// [{ address, chainId, name, asset, assetSymbol, totalAssets, targetWeightBps, allocationPct }]
필드의미
name수익원/프로토콜 식별 — IAdapter.name() (예: Compound V3, Aave V3, Morpho Blue, Institutional Lending Escrow). 미구현 어댑터는 null
totalAssets이 어댑터의 현재 평가액 (Amount — 배치+pending 포함)
targetWeightBps목표 배분 비중(bps, 합 10000) — 미설정(폴백 배치)·멀티체인이면 null
allocationPct실제 배분 비율(%) — 싱글=평가액 기준, 멀티=투입원금 기준
chainId이 어댑터가 배치된 체인 (멀티체인은 어댑터마다 다를 수 있음)

실제 반환 (라이브)

상품수익원 (name · 비중)
B · JPYCJPYC/USDC Yield 30% · Morpho Blue 70%
C · USDCInstitutional Lending Escrow 100%
A · USDC (멀티)Compound V3 (허브 60% + Sepolia 40%)
D · USDC (멀티)Aave V3 57% · Robinhood Basket (Uniswap V3 Mirror) 43%
i어댑터 열거 경로 — 싱글체인은 상품 Valuation의 어댑터 목록·targetWeights, 멀티체인은 최근 정산 기록(get_adapter_valuations)의 어댑터별 투입원금. 프리컴파일 get_adapters는 레지스트리가 채워지면 그쪽으로 스위치합니다.
Data API Yield sources

Yield sources — which protocol, how much

Which yield protocols the product is deploying into right now, per-adapter. Each adapter's name(), current value, and allocation in one call.

ts
const sources = await sdk.yieldSources()
// [{ address, chainId, name, asset, assetSymbol, totalAssets, targetWeightBps, allocationPct }]
FieldMeaning
nameProtocol id — IAdapter.name() (e.g. Compound V3, Aave V3, Morpho Blue). null if the adapter doesn't implement it
totalAssetsCurrent value of this adapter (deployed + pending)
targetWeightBpsTarget allocation (bps, sums 10000) — null when unset / multichain
allocationPctActual allocation % — single-chain by value, multichain by principal

Enumeration: single-chain reads the product Valuation's adapter list + targetWeights; multichain reads the latest settlement's get_adapter_valuations (per-adapter principal).

데이터 API sourceValuations()

sourceValuations() — 수익원 실평가

회차별 수익원(어댑터) 평가 내역 — 배치 원금·USD 평가·자산 포지션. 상세·운영 뷰용입니다.

sourceValuations(round?): Promise<SourceValuation[] | null>
필드타입화면에서
chainId · adapternumber · Address어느 체인의 어느 수익원인지
principalAmount배치된 누적 원금 (기준 자산)
totalUsdnumberNAV 포함분 합계 (USD) — 원금 대비 수익 파악
positions[]{ asset, amount, priceUsd, usdValue, counted }자산별 포지션 — counted:false는 NAV 미포함(스왑 전 리워드 토큰 등)

round 생략 시 최신 회차. 미기록 회차면 null — 이 view 외에는 조회 경로가 없는 데이터입니다 (get_adapter_valuations).

결과 예시 — 테스트베드 라이브

live · testbed
await omnifi.sourceValuations(14)
[
  { chainId: 49088,    adapter: '0x4D1ab20B…',  // Bifrost 수익원 어댑터
    principal: { formatted: '1,379.99', symbol: 'USDC' },
    totalUsd: 1380.15,                          // NAV 포함분 합계(USD)
    positions: [ { asset: '0x…', amount: 1380150000n, priceUsd: 1.0, usdValue: 1380.15, counted: true } ] },
  { chainId: 11155111, adapter: '0xe12061DF…',  // Sepolia 수익원 어댑터
    principal: { formatted: '959.99', symbol: 'USDC' }, totalUsd: 960.10, positions: [ … ] }
]
Data API sourceValuations()

sourceValuations() — yield-source valuations

Per-round adapter valuation detail — deployed principal, USD value, asset positions.

sourceValuations(round?): Promise<SourceValuation[] | null>

Each entry: chainId/adapter, principal (base asset), totalUsd (NAV-counted sum), positions[] (per-asset amount, USD price, counted — false for pre-swap reward tokens). Defaults to the latest round; null when not recorded.

데이터 API whitelistStatus()

whitelistStatus() — 참여 자격 · 전파 진행

유저가 어느 볼트에 등록돼 있는지, 최근 등록/해제가 어디까지 전파됐는지 — 온보딩·운영 화면용입니다.

whitelistStatus(user): Promise<WhitelistState>

반환 필드 — WhitelistState

필드타입의미
allRegisteredboolean전 볼트 등록 완료 여부 — canInvest와 동일 판정. false면 온보딩 안내
vaultsVaultWhitelist[]볼트(트랜치 × 체인) 단위 항목 — overview().tranches와 같은 순서

VaultWhitelist — vaults[] 항목 필드

필드타입의미 · null 조건
tranche'senior' | 'junior'트랜치 종류
chainIdnumber이 볼트의 체인. 예: 11155111(Sepolia)
registeredboolean허브 정본(is_tranche_investor) 등록 여부 — 부분 등록 진단
actionWhitelistAction | null최근 grant/revoke의 전파 진행. 기록 없으면 null

WhitelistAction — action 필드

필드타입의미
kind'grant' | 'revoke'등록 / 해제
appliedboolean스포크 전파까지 완료됐는지 (반영 완료 단계 도달)
stepsTimelineStep[]전파 파이프라인 — 변경 접수 → 브릿지 전송 → 반영 완료. 단계별 tx·허브 기록 시각(TimelineStep 참조)
i부분 등록(일부 볼트만 grant됨)을 잡아내는 게 핵심 용도 — 예: 4볼트 중 3개만 등록된 유저는 나머지 볼트 입금에서 NOT_WHITELISTED가 됩니다. 운영자는 이 화면으로 어느 볼트의 grant가 누락/전파 중인지 즉시 확인합니다.

결과 예시 — 테스트베드 라이브

live · testbed
await omnifi.whitelistStatus(userAddress)
{
  allRegistered: false,               // 일부 볼트 미등록 → 온보딩 안내
  vaults: [
    { tranche: 'senior', chainId: 49088,    registered: true,
      action: { kind: 'grant', applied: true,
                steps: [ '변경 접수'✓, '반영 완료'✓ ] } },   // 허브 볼트 = Bridge leg 없음(길이 2)
    { tranche: 'senior', chainId: 11155111, registered: true,
      action: { kind: 'grant', applied: true,
                steps: [ '변경 접수'✓, '브릿지 전송'✓, '반영 완료'✓ ] } }, // 스포크 볼트(길이 3)
    { tranche: 'junior', chainId: 49088,    registered: true,  action: { … } },
    { tranche: 'junior', chainId: 11155111, registered: false, action: null }   // 부분 등록 — 이 볼트 입금 시 NOT_WHITELISTED
  ]
}
Data API whitelistStatus()

whitelistStatus() — eligibility & propagation

Per-vault canonical registration and the latest grant/revoke propagation — for onboarding and ops screens.

whitelistStatus(user): Promise<WhitelistState>

Return fields — WhitelistState

FieldTypeMeaning
allRegisteredbooleanRegistered on every vault — mirrors canInvest. false → show onboarding
vaultsVaultWhitelist[]Per (tranche × chain) vault — same order as overview().tranches

VaultWhitelist — vaults[] item fields

FieldTypeMeaning · null
tranche'senior' | 'junior'Tranche type
chainIdnumberThis vault's chain, e.g. 11155111 (Sepolia)
registeredbooleanHub-canonical (is_tranche_investor) status — catches partial registration
actionWhitelistAction | nullLatest grant/revoke propagation; null if none recorded

WhitelistAction — action fields

FieldTypeMeaning
kind'grant' | 'revoke'Registration / removal
appliedbooleanPropagated to the spoke (reached the applied step)
stepsTimelineStep[]Pipeline — requested → bridge → applied, per-step tx/time (see TimelineStep)
데이터 API settlementStatus()

settlementStatus() — 정산 회차별 크로스체인 기록

정산 회차 하나로 해당 사이클의 전 과정을 조회합니다 — 개시 tx, 체인별 단계(NAV 수집→확정 반영), 브릿지 시도 이력(성공·롤백)을 포함합니다. "정산 사이클 조회" 화면의 데이터 소스입니다.

settlementStatus(round): Promise<SettlementStatus>

임의 회차 안전 — 미개시 회차도 revert 없이 status 'Queued'로 반환되므로 마음껏 폴링·조회할 수 있습니다. 회차별 확정 가격·NAV 시계열priceHistory()가 담당하고, 이 API는 처리 과정(tx) 기록을 담당합니다.

반환 필드 — SettlementStatus

필드타입화면에서
status · statusLabel'Queued'|'SettleStarted'|'Settled' · string상태 뱃지 — 미개시(회색) · 진행 중(파랑, 폴링 권장) · 완료(초록)
settleStartedTimelineStep정산 개시(SettleStarted) tx·허브 기록 시각 — 온체인 settle_started_tx
chains[]{ chainId, steps: TimelineStep[] }체인별 단계 — NAV 수집 전달 → NAV 수집 → NAV 회신 → NAV 확정 (+ 분배가 있으면 확정 반영 → 정산 완료). 단계별 tx·시각·롤백(failed)
progress{ done, total }체인 완료 수 — "체인 1/1 완료"
bridges[]{ chainId, legs[] }leg별(수집 전달·회신·확정 반영) 브릿지 시도 전체 이력 — 성공·롤백 순서대로, 각 시도 tx·시각. steps가 숨기는 실패까지 보임

결과 예시 — 테스트베드 라이브 (실사고 기록)

live
await omnifi.settlementStatus(11)
{
  round: 11, status: 'Settled', statusLabel: '완료',
  settleStarted: { label: '정산 개시', labelEn: 'SettleStarted', done: true, txHash: '0x614f…', at: 08-21T03:58 },
  chains: [{ chainId: 11155111, steps: [ 'NAV 수집 전달'✓, 'NAV 수집'✓, 'NAV 회신'✓, 'NAV 확정'✓ ] }],
  bridges: [{ chainId: 11155111, legs: [
    { label: 'NAV 수집 전달', attempts: [
      { statusLabel: '롤백', reverted: true,  txHash: '0xbd9f…', at: 07:40 },  // 실제 브릿지 실패 기록
      { statusLabel: '성공', reverted: false, txHash: '0xead9…', at: 11:16 } ] }, // 재시도 성공
    { label: 'NAV 회신', attempts: [{ statusLabel: '성공', … }] } ] }]
}

"확정 반영이 없는" 회차 — 빈 정산

승인된 요청이 없는 정기 회차는 확정 반영(분배) 단계가 steps에 아예 없습니다 — 분배할 결과가 없어 브릿지가 발신되지 않은 것으로, 미도달·실패가 아닙니다 (노드 규칙: "배열에 항목 없음 = 해당 없음"). 화면에는 "NAV만 갱신한 정기 정산" 안내를 병기하는 것을 권장합니다.

i과거 회차 전체를 훑으려면 settlementStatus를 1..overview().settlementRound로 순회하면 됩니다 — 미개시 회차 포함 전부 안전. 갱신은 진행 중(Triggered) 회차만 10초 폴링, 완료 회차는 불변입니다.
Data API settlementStatus()

settlementStatus() — per-round cross-chain record

One round number → the full processing record: trigger tx, per-chain steps (NAV collect → finalize), and the complete bridge-attempt history (successes and rollbacks).

Safe for any round — untriggered rounds return status 'Queued' without reverting. Fields: status/statusLabel (badge), trigger, chains[].steps (per-step tx/time/failed), progress, bridges[].legs[].attempts (ordered success/rollback history — the failures the steps array hides). Rounds with no approved requests have no finalize step at all (nothing to distribute — absent, not failed). Price/NAV series per round live in priceHistory(); poll only Triggered rounds — settled ones are immutable.

데이터 API estimateDeposit / estimateRedeem

예상 수령량 — estimateDeposit / estimateRedeem

금액 입력 중 예상 수령량을 산출합니다. 직전 정산가 기준 추정치입니다.

estimateDeposit(tranche, amount: string): Promise<Amount | null>
estimateRedeem(tranche, shares: string): Promise<Amount | null>

반환

케이스반환표기
정상AmountestimateDeposit → 예상 share (symbol = share 토큰) · estimateRedeem → 지급 예정액 (symbol = 기준 자산). 소수 4자리 절사
첫 정산 전 (기준 가격 없음)null"정산 후 확정" — 입력은 차단하지 않음
금액 파싱 불가/0throw INVALID_AMOUNT입력 검증에 그대로 활용

표기 규칙

  • 결과 앞에 "예상 ≈"를 표기합니다 — 확정은 정산 시점입니다.
  • 상환의 추정액은 표준어로 "지급 예정액"입니다 — "확정 지급액"은 정산 후에만 사용합니다 (사내 용어 규칙).
  • 입력 debounce(250ms 권장) 후 호출합니다.

결과 예시 — 테스트베드 라이브

live · testbed
await omnifi.estimateDeposit('senior', '100')
{ formatted: '99.993', symbol: 'oSR', raw: 99993000000000000000n, decimals: 18 }
// 100 USDC 입금 시 받을 예상 share — 직전 정산가(≈1.00007) 기준

await omnifi.estimateRedeem('senior', '100')
{ formatted: '100.0069', symbol: 'USDC', … }
// share 100 상환 시 지급 예정액 — 첫 정산 전이면 두 함수 모두 null
Data API estimateDeposit / estimateRedeem

Estimates — estimateDeposit / estimateRedeem

Live "you will receive ≈" hints while typing, based on the latest settled price.

estimateDeposit(tranche, amount: string): Promise<Amount | null>
estimateRedeem(tranche, shares: string): Promise<Amount | null>

Returns

CaseReturnsDisplay
NormalAmountestimateDeposit → estimated shares (symbol = share token) · estimateRedeem → estimated payout (symbol = base asset). Floored to 4 dp
No settlement yetnullShow "finalized after settlement"; keep input enabled
Invalid/zero amountthrows INVALID_AMOUNTUse directly for input validation
  • Prefix with "est. ≈" — final amounts are fixed at settlement.
  • Debounce input (~250 ms).
액션 API deposit()

deposit() — 입금 신청

단일 호출로 검증부터 영수증 확인까지 수행합니다. 성공 시 requestId가 반환되어 타임라인과 즉시 연결됩니다.

deposit(tranche, amount: string, opts?: { chainId? }): Promise<{ txHash, requestId, approveTxHash }>
i멀티 볼트 상품: overview().depositChains가 2개 이상이면 opts.chainId로 입금 체인을 지정합니다 — 폴백 순서는 opts.chainIdcreate({ defaultChainId }) → 상품의 첫 체인(결정적). 상품에 없는 체인을 지정하면 CHAIN_NOT_SUPPORTED가 발생합니다. redeem·receive·estimate*도 동일한 opts.chainId를 받습니다.

내부 처리 순서

  1. 지갑 연결 확인 → NOT_CONNECTED
  2. 금액 파싱 → INVALID_AMOUNT
  3. 잔액 확인 → INSUFFICIENT_BALANCE
  4. 투자 자격(화이트리스트) 확인 → NOT_WHITELISTED
  5. 스포크 체인(Sepolia)으로 네트워크 자동 전환
  6. approve 부족 시 승인 tx 선행 (확정 대기 포함)
  7. 신청 tx 전송 → 영수증 대기 → 이벤트에서 requestId 추출

지갑 서명은 최대 2회(승인+신청), 기승인 상태면 1회입니다.

반환

필드타입의미
txHashHash입금 신청 tx 해시 — 익스플로러 링크
requestIdHex | null요청 식별자 — activity() 항목과 매칭. 이벤트 파싱 실패 시 null(폴링으로 자연 연결)
approveTxHashHash | null자산 승인 tx 해시 — 승인이 필요 없었으면 null

결과 예시 — 테스트베드 라이브

live · testbed
await omnifi.deposit('senior', '100.5')
{
  txHash:        '0xce87d8c9cb1a…',   // 신청 tx (Sepolia)
  requestId:     '0x000000020000000200…',  // activity()·investmentHistory()로 추적
  approveTxHash: '0x4a1f…'             // 승인 선행 시 · 이미 승인됐으면 null
}
// 이후 흐름은 자동 — myAccount 폴링으로 processing → receivable 전환 확인
Action API deposit()

deposit() — request a deposit

One call runs validation through receipt confirmation, returning a requestId that joins the timeline.

deposit(tranche, amount: string, opts?: { chainId? }): Promise<{ txHash, requestId, approveTxHash }>
iMulti-vault products: when overview().depositChains has more than one entry, pass opts.chainId to pick the deposit chain — fallback order is opts.chainIdcreate({ defaultChainId }) → the product's first chain (deterministic). A chain the product doesn't serve throws CHAIN_NOT_SUPPORTED. redeem, receive and estimate* accept the same option.
  1. Wallet connected → NOT_CONNECTED
  2. Parse amount → INVALID_AMOUNT
  3. Balance check → INSUFFICIENT_BALANCE
  4. Whitelist check → NOT_WHITELISTED
  5. Auto-switch to the spoke chain (Sepolia)
  6. Approve first if needed (waits for confirmation)
  7. Send request tx → wait for receipt → extract requestId

At most two wallet signatures; one if already approved.

Returns

FieldTypeMeaning
txHashHashRequest tx hash — explorer link
requestIdHex | nullRequest identifier joining activity(); null on rare event-parse failure (polling reconnects)
approveTxHashHash | nullApprove tx hash, or null if not needed
액션 API redeem()

redeem() — 상환 신청

보유 share를 자산으로 상환하는 신청입니다. 흐름은 deposit과 동일하며 두 가지가 다릅니다.

redeem(tranche, shares: string): Promise<{ txHash, requestId, approveTxHash }>
  • 수량 단위가 share입니다 — 전량 상환은 formatUnits(shares.raw, decimals)를 입력값으로 사용합니다.
  • 화이트리스트 확인이 없습니다 — share 보유자는 이미 자격이 검증된 상태입니다.
!신청 후 취소가 불가능합니다. 호출 전 "지급 예정액 · 취소 불가" 확인 모달이 UX 요구사항입니다 (estimateRedeem() 활용).

반환

필드타입의미
txHashHash상환 신청 tx 해시 — 익스플로러 링크
requestIdHex | null요청 식별자 — activity() 항목과 매칭. 이벤트 파싱 실패 시 null(폴링으로 자연 연결)
approveTxHashHash | nullshare 승인 tx 해시 — 승인이 필요 없었으면 null

결과 예시 — 테스트베드 라이브

live · testbed
await omnifi.redeem('senior', '10')
{ txHash: '0x…', requestId: '0x000000020000000200…', approveTxHash: '0x…' }
// 반환 형태는 deposit과 동일 · 단 신청 후 취소 불가(확인 모달 필수)
Action API redeem()

redeem() — request a redemption

Redeems held shares for the asset. Same flow as deposit, two differences.

redeem(tranche, shares: string): Promise<{ txHash, requestId, approveTxHash }>
  • Quantity is in shares — for "redeem all", feed formatUnits(shares.raw, decimals) back in.
  • No whitelist check — holding shares implies eligibility.
!Redemptions cannot be cancelled. Show a confirmation modal with the estimate and the no-cancel notice first.

Returns

FieldTypeMeaning
txHashHashRedeem request tx hash
requestIdHex | nullJoins activity(); null on rare parse failure
approveTxHashHash | nullShare-approve tx hash, or null
액션 API receive()

receive() — 수령

정산 확정된 share(입금) 또는 자산(상환)을 지갑으로 수령합니다. 마지막 유저 액션입니다.

receive(tranche, kind: 'deposit'|'redeem'): Promise<{ txHash, received: Amount }>
  • myAccount()의 해당 방향 상태가 receivable일 때만 호출합니다 — 그 외에는 NOTHING_TO_RECEIVE가 발생합니다 (안전).
  • 확정분 전액 일괄 수령입니다 — 요청별 부분 수령은 지원되지 않습니다.
  • 수령 tx도 스포크 체인에서 실행됩니다 — 자동 전환, 지갑 서명 1회.

반환

필드타입의미
txHashHash수령 tx 해시
receivedAmount실제 수령량 — 입금 수령이면 share(symbol = share 토큰), 상환 수령이면 자산. 완료 토스트에 formatted + symbol 그대로 사용

결과 예시 — 테스트베드 라이브

live · testbed
await omnifi.receive('senior', 'deposit')   // 'deposit' | 'redeem'
{ txHash: '0x411cd50bed…', received: { formatted: '199.9995', symbol: 'oSR', … } }
// received — 실제 수취량(입금 수령=share · 상환 수령=기준 자산). status가 'receivable'일 때만 호출
Action API receive()

receive() — claim finalized funds

Brings finalized shares (deposits) or assets (redemptions) into the wallet. The final user action.

receive(tranche, kind: 'deposit'|'redeem'): Promise<{ txHash, received: Amount }>
  • Call only when receivable; otherwise NOTHING_TO_RECEIVE is thrown (safe).
  • Receives the full finalized balance at once — no partial claims.
  • Runs on the spoke chain — auto-switched, one signature.

Returns

FieldTypeMeaning
txHashHashReceive tx hash
receivedAmountActual received amount — shares for deposit receives, asset for redeem receives. Use formatted + symbol in the success toast
액션 API faucet()

faucet() — 테스트 자산 수급 테스트넷 전용

체인마다 배포된 UniversalFaucet에서 입금 자산을 지급받습니다. mint가 아니라 운영자가 미리 채워둔 잔고에서 전송하는 방식입니다.

!메인넷에는 존재하지 않는 기능입니다. 테스트넷 데모 전용 — 프로덕션 빌드의 화면에 노출하지 마세요. 메인넷에서 호출하면 파우셋 컨트랙트가 없어 실패합니다.
ts
// 멀티체인 — 입금 체인이 여러 개라 chainId 명시 (지갑을 그 체인으로 전환 후 claim)
const txHash = await omnifi.faucet(11155111)          // 1,000 (기본)
await omnifi.faucet(49088, 500_000000n)               // 수량 지정 (자산 decimals 기준 raw)

// 싱글체인 — 상품 체인의 입금 자산을 claim
await sdk.faucet()                                    // 1,000 (기본)
항목
1회 상한10,000 (토큰 단위)
쿨다운주소·토큰당 1시간 — 초과 시 CooldownActive revert
가스해당 체인 가스 토큰 필요 (Sepolia ETH · BFC 등) — 파우셋은 ERC-20만 지급
주소OMNIFI_FAUCETS 레지스트리 (허브·Sepolia·Robinhood 체인당 1개)

잔고 소진 시 지급이 revert됩니다 — 운영자 재충전 필요. 지원되지 않는 토큰은 TokenNotSupported.

Action API faucet()

faucet() — test funds testnet-only

Claims the deposit asset from the per-chain UniversalFaucet — a transfer from a pre-funded balance, not a mint.

!This does not exist on mainnet. Testnet demo only — never expose it in production UI; on mainnet the call fails (no faucet contract).
ts
// multichain — several deposit chains, so pass chainId (wallet switches, then claims)
const txHash = await omnifi.faucet(11155111)          // 1,000 (default)
await omnifi.faucet(49088, 500_000000n)               // explicit raw amount

// single-chain — claims the product chain's deposit asset
await sdk.faucet()
ItemValue
Max per claim10,000 (token units)
Cooldown1 hour per address·token — CooldownActive revert if exceeded
GasNative gas still required (Sepolia ETH · BFC) — the faucet dispenses ERC-20 only
AddressesOMNIFI_FAUCETS registry (one per chain: hub · Sepolia · Robinhood)
가이드 화면 구성 레시피

화면 구성 레시피

대표 화면 4종을 SDK 호출로 구성하는 방법입니다. 파트너 앱의 실제 구현과 동일한 패턴입니다.

① 투자 위젯 — ActionState 기반 분기

tsx
const action = tab === 'deposit' ? tranche.deposit : tranche.redeem

const label =
  action.status === 'receivable' ? `${action.amount.formatted} ${action.amount.symbol} 수령하기`
  : action.status === 'processing' ? `${action.statusLabel} 중`  // "정산 대기 중" — 메인은 요청 상태 축
  : tab === 'deposit' ? '입금 신청' : '상환 신청'
// 세부 단계(자금 공급 중 등)는 action.stageLabel / action.steps — 상세 영역에 표시

MAX 버튼: formatUnits(balance.raw, balance.decimals)를 입력값으로 사용하면 반올림 손실 없이 전량이 입력됩니다.

② 진행 타임라인 카드

tsx
{(await omnifi.activity(user)).map((a) => (
  <Card key={a.requestId}>
    <Row>{a.tranche} {a.kind === 'deposit' ? '입금' : '상환'} · {a.amount.formatted} — <Badge>{a.phase}</Badge></Row>
    <Chips>{a.steps.map((s) => <Chip done={s.done}>{s.label}</Chip>)}</Chips>
  </Card>
))}

③ 가격 차트

tsx
const data = (await omnifi.priceHistory()).map((p) => ({
  round: p.round, senior: p.senior, junior: p.junior, at: p.at,
}))
// 툴팁 라벨: `정산 #${round} · ${at.toLocaleString('ko-KR')}`

④ 상품 헤더 — 기준 시각 병기

tsx
<Stat label="TVL (정산 확정치)" value={ov.tvl ? `${ov.tvl.formatted} ${ov.assetSymbol}` : '기록 없음'} />
<p>{ov.settledAt && `${fmt(ov.settledAt)} 정산 #${ov.settlementRound} 기준`}</p>
<p>다음 정산 {fmt(ov.nextSettlementAt)} · 신청 마감 {fmt(ov.orderCloseAt)}</p>
Guides UI Recipes

UI Recipes

How the four common screens compose from SDK calls — the same patterns used by the partner app.

① Invest widget — branch on ActionState

tsx
const action = tab === 'deposit' ? tranche.deposit : tranche.redeem

const label =
  action.status === 'receivable' ? `Receive ${action.amount.formatted} ${action.amount.symbol}`
  : action.status === 'processing' ? action.statusLabel   // request-status axis drives the CTA
  : tab === 'deposit' ? 'Deposit' : 'Redeem'

② Progress timeline card

tsx
{(await omnifi.activity(user)).map((a) => (
  <Card key={a.requestId}>
    <Row>{a.tranche} {a.kind} · {a.amount.formatted} — <Badge>{a.phase}</Badge></Row>
    <Chips>{a.steps.map((s) => <Chip done={s.done}>{s.label}</Chip>)}</Chips>
  </Card>
))}

③ Product header — with the reference time

tsx
<Stat label="TVL (as settled)" value={ov.tvl ? `${ov.tvl.formatted} ${ov.assetSymbol}` : 'No record'} />
<p>{ov.settledAt && `as of settlement #${ov.settlementRound}, ${fmt(ov.settledAt)}`}</p>
가이드 에러 처리

에러 처리 — 코드 11종과 화면 대응

catch 처리에 필요한 내용 전체입니다.

기본 패턴

ts
try {
  await omnifi.deposit('senior', input)
} catch (e) {
  if (e instanceof OmniFiError) {
    if (e.code === 'NOT_WHITELISTED') return goOnboarding()
    if (e.code === 'USER_REJECTED') return
    toast(e.userMessage)   // 기본 처리는 이 한 줄로 충분
  }
}

코드 전체 표

e.code발생 시점화면 대응
NOT_CONNECTED지갑 미연결지갑 연결 유도
INVALID_AMOUNT금액 파싱 불가/0입력 검증 표시
INSUFFICIENT_BALANCE잔액 부족userMessage 표시
NOT_WHITELISTED투자 자격 없음온보딩으로 유도
NOTHING_TO_RECEIVE수령 가능분 없음버튼 상태 갱신
USER_REJECTED지갑에서 거절무시 권장
INSUFFICIENT_GAS수수료(가스) 부족가스 안내 — 문구가 체인별 통화(BFC/ETH)로 자동 생성
CHAIN_NOT_SUPPORTED상품에 없는 체인 지정overview().depositChains 확인 유도
PRODUCT_NOT_FOUND허브 팔렛에 상품 미등록운영 안내(재등록 대기)
RPC_UNAVAILABLE노드 무응답재시도 버튼
TX_FAILED그 외 온체인 실패userMessage 표시
e.cause(원본 오류)는 콘솔·모니터링 전용입니다 — 유저 화면에 노출하지 않습니다.
Guides Error Handling

Error handling — eleven codes and their UI responses

Everything a catch block needs.

e.codeWhenUI response
NOT_CONNECTEDNo wallet connectedPrompt connection
INVALID_AMOUNTUnparseable/zero amountInput validation
INSUFFICIENT_BALANCEBalance too lowShow userMessage
NOT_WHITELISTEDNot eligibleRoute to onboarding
NOTHING_TO_RECEIVENothing receivableRefresh button state
USER_REJECTEDRejected in walletUsually ignore
INSUFFICIENT_GASNot enough gas fundsGas guidance — message auto-names the chain's currency (BFC/ETH)
CHAIN_NOT_SUPPORTEDChain not served by productPoint to overview().depositChains
PRODUCT_NOT_FOUNDProduct missing on hub palletOps notice (await re-registration)
RPC_UNAVAILABLENode unreachableRetry button
TX_FAILEDOther on-chain failureShow userMessage
e.cause is for consoles and monitoring only. Locale: userMessage defaults to Korean — switch with create({ locale: 'en' }) or setOmniFiLocale('en'), or read a specific language via e.getMessage('en').
가이드 폴링 전략

갱신(폴링) 전략

크로스체인 특성상 이벤트 구독보다 폴링이 단순하며 충분합니다. SDK가 내부적으로 호출을 배칭(스포크 multicall · 허브 JSON-RPC 배치)하므로 폴링 비용은 왕복 수 회 수준입니다.

대상주기이유
myAccount · activity10~15초진행 단계 전환 감지에 충분 (브릿징·전파는 분 단위)
overview폴링에 포함 가능가볍고 nextSettlementAt 카운트다운의 근거
priceHistorysettlementRound 변경 시정산 사이에는 불변
  • 액션 성공 직후 즉시 1회 갱신 — 체감 반응성은 이것으로 확보됩니다.
  • 폴링 실패는 다음 주기에 회복 — 화면을 비우지 않습니다.
Guides Polling Strategy

Polling strategy

Polling beats event subscriptions on simplicity here — and the SDK batches calls internally (multicall on the spoke, JSON-RPC batching on the hub), so a poll costs a few round-trips.

TargetIntervalWhy
myAccount · activity10–15 sStage transitions are minutes-scale
overviewMay ride the same pollCheap; backs the countdown
priceHistoryOn settlementRound changeImmutable between settlements
참고 FAQ

FAQ · 트러블슈팅

연동 과정에서 자주 발생하는 질문과 해결 방법입니다.

신청 후 수령 버튼이 표시되지 않습니다

정상 동작입니다. 신청 → 수령 가능 전환은 다음 정산이 완료되어야 이루어집니다. 예정 시각은 overview().nextSettlementAt이며, 그 사이 상태는 processing + stageLabel로 진행이 표시됩니다. orderCloseAt 이후의 신청은 한 회차 뒤로 배정됩니다.

estimateDeposit이 null을 반환합니다

상품의 첫 정산 전이라 기준 가격이 없는 상태입니다. "정산 후 확정"으로 표기하고 입력은 차단하지 않습니다.

deposit이 NOT_WHITELISTED 오류를 반환합니다

해당 지갑이 상품 화이트리스트에 등록되지 않은 상태입니다. 온보딩(KYC) 흐름으로 안내하며, 등록은 운영자가 수행합니다. myAccount().canInvest로 사전 판별이 가능합니다.

tx가 INSUFFICIENT_GAS로 실패합니다

신청·수령 tx는 Sepolia에서 실행되므로 소량의 Sepolia ETH가 필요합니다. 퍼블릭 파우셋에서 수급할 수 있습니다. (가스 대납은 로드맵 항목입니다)

모든 조회가 RPC_UNAVAILABLE을 반환합니다

허브 노드(테스트베드, 사내망) 연결 문제일 가능성이 높습니다 — 퍼블릭 Bifrost 노드에는 프리컴파일이 없어 대체가 불가합니다. VPN 연결과 노드 상태를 확인하고, 주소가 변경된 경우 create({ hubRpcUrl })로 지정합니다.

테스트 자산(USDC·JPYC) 수급 방법

faucet()으로 셀프서비스 수급합니다 — 체인마다 배포된 UniversalFaucet에서 입금 자산을 지급받습니다(1회 상한 10,000 · 주소당 쿨다운 1시간). 멀티체인은 omnifi.faucet(chainId), 싱글체인은 sdk.faucet(). 자세한 사용법은 faucet() 페이지.

테스트넷 전용 기능입니다 — 메인넷에는 파우셋이 존재하지 않으며, 프로덕션 화면에 노출하면 안 됩니다.

과거 이력(완료된 요청·수령 기록) 조회 방법

고수준 API는 진행 중(activity)만 다룹니다. 완료 이력은 로우레벨 omnifi.inner.requestHistory() / receiveHistory()(페이지네이션, 페이지당 최대 50건)로 조회합니다.

Reference FAQ

FAQ · Troubleshooting

Common questions during integration.

The receive button doesn't appear after a request

Expected — requests become receivable only after the next settlement completes (overview().nextSettlementAt). Requests after orderCloseAt roll one round later.

estimateDeposit returns null

No settlement has run yet, so there is no reference price. Show "finalized after settlement".

deposit throws NOT_WHITELISTED

The wallet is not whitelisted. Route to onboarding; detect beforehand with myAccount().canInvest.

Transactions fail with INSUFFICIENT_GAS

User txs run on Sepolia and need a little Sepolia ETH. (Gas sponsorship is on the roadmap.)

Every read returns RPC_UNAVAILABLE

Likely hub-node (internal testbed) connectivity — check VPN/node status; public Bifrost nodes cannot substitute.

Getting test assets (USDC · JPYC)

Self-service via faucet() — a UniversalFaucet deployed per chain dispenses the deposit asset (max 10,000 per claim, 1-hour cooldown per address). Multichain: omnifi.faucet(chainId); single-chain: sdk.faucet(). See faucet().

Testnet-only. No faucet exists on mainnet — never expose this in production UI.

Reading completed history

Use the low-level omnifi.inner.requestHistory() / receiveHistory() (paginated, max 50).

참고 용어집

용어집

화면 문구와 커뮤니케이션에 사용하는 표준어입니다. 사내 용어 정본과 정합합니다.

용어영문정의
트랜치tranche한 상품 안의 위험·수익 층 (Senior/Junior)
shareshare투자 지분 토큰 — 번역하지 않음 ("보유 지분 단위" 설명 병기)
입금deposit유저 → 상품으로 자산을 넣는 신청 ("예치" 사용 금지)
상환redeemshare를 자산으로 되돌리는 신청 ("출금" 사용 금지)
수령receive확정된 share/자산을 지갑으로 가져오는 마지막 유저 액션
정산settlement주기적으로 가격을 확정하고 신청을 일괄 처리하는 사이클
정산 회차settlementRound정산의 순번 (#1, #2 …)
신청 마감orderCloseAt해당 회차에 포함되는 신청의 마감 시각
수령 가능receivable정산 확정 후 수령만 남은 상태
TVL / 상품 NAVproductNav상품 운용 자산 전체의 정산 확정 평가액
i금칙어: "예치"(입금/공급 혼동), "출금"(상환/수령 혼동), 한정어 없는 "NAV". 유저 대상 문구는 위 표준어만 사용합니다.
Reference Glossary

Glossary

Standard vocabulary for UI copy, aligned with the internal terminology spec.

TermDefinition
trancheA risk/return layer within one product (Senior/Junior)
shareThe investment unit token
depositUser → product asset request
redeemShare → asset request
receiveThe final user action: claiming finalized shares/assets
settlementThe periodic cycle that finalizes prices and processes requests in batch
settlementRoundSequential settlement number
orderCloseAtCutoff for inclusion in the round
receivableFinalized; only receiving remains
TVL / product NAVSettlement-finalized value of all product assets
참고 아키텍처

아키텍처와 로우레벨 접근

고수준 API 하부 구조 설명과 세부 제어 경로입니다.

2층 구조

진입점대상
고수준 API (이 문서)OmniFi프론트·파트너 — 휴먼 단위, 단일 호출, 한국어 오류
로우레벨omnifi.inner (MultiChainTrancheSDK)개별 view·페이지네이션·정산 사이클 체인별 진행

허브 프리컴파일 5종 — 조회의 원천

프리컴파일주소답하는 질문
TrancheSystem0x0000000000000000000000000000000000000200상품이 어떻게 구성되어 있는가 (view 4종)
Investments0x0000000000000000000000000000000000000201얼마로 확정되었는가 — 정산·요청·승인 결과 (view 9종)
TranchePermissions0x0000000000000000000000000000000000000202이 지갑이 투자 가능한가 — 화이트리스트
TxRegistry0x0000000000000000000000000000000000000203지금 어디까지 진행되었는가 — 크로스체인 단계별 tx 증거 (view 6종)
CustomFlows0x0000000000000000000000000000000000000204custom flow(리워드 클레임 등)가 어디까지 진행되었는가 (view 4종)

고수준 API의 activity()phase는 Investments("확정 결과")와 TxRegistry("진행 상태")의 조합입니다. 스포크(Sepolia)는 ERC-7540 볼트 표준 — 잔액과 수령 가능액의 정본입니다.

호출 배칭

SDK는 조회를 내부적으로 묶어 전송합니다 — 스포크는 Multicall3 집계 + JSON-RPC HTTP 배치, 허브는 JSON-RPC HTTP 배치(테스트베드 체인에 Multicall3 미배포). 소비자 코드는 변경 없이 Promise.all로 병렬 호출하면 자동으로 묶입니다.

로우레벨 사용 예

ts
// 완료 포함 요청 이력 (페이지네이션 ≤50)
const { requestIds, total } = await omnifi.inner.requestHistory(user, 0, 20)

// 정산 사이클의 체인별 진행 (운영 뷰)
const sp = await omnifi.inner.settlementProgress(2)
Reference Architecture

Architecture and low-level access

What sits under the facade, and how to reach it.

PrecompileAddressQuestion it answers
TrancheSystem0x0000000000000000000000000000000000000200How is the product configured (4 views)
Investments0x0000000000000000000000000000000000000201What was finalized (9 views)
TranchePermissions0x0000000000000000000000000000000000000202Is this wallet eligible
TxRegistry0x0000000000000000000000000000000000000203How far has it progressed (6 views)
CustomFlows0x0000000000000000000000000000000000000204Where a custom flow (e.g. reward claim) stands (4 views)

The facade's activity()/phase combine Investments ("results") with TxRegistry ("progress"). The spoke (Sepolia) is the ERC-7540 vault standard — the source of truth for balances and receivables.

Call batching

Reads are batched internally — Multicall3 aggregation plus JSON-RPC HTTP batching on the spoke, JSON-RPC HTTP batching on the hub (no Multicall3 on the testbed chain). Consumer code just uses Promise.all; batching is automatic.

참고 환경 · 주소

환경 · 주소

현재 테스트베드 기준 구성입니다. 배포 환경 변경 시 이 페이지만 갱신됩니다.

항목
패키지@omnifi/sdk (구명 rwa-tranche-sdk — RwaTranche/RwaError 별칭 유지)
기본 상품시나리오 A (productId 0x0000000200000009 — USDC 기준자산) — OmniFi.create() 기본값
시나리오 A멀티체인 · USDC · 허브 49088 + 스포크 Sepolia — OMNIFI_SETS.a
시나리오 B싱글체인 · JPYC(18dec) · Sepolia — TrancheSDK.create({ set: 'b' }) (0x0000000100000004)
시나리오 C싱글체인 · USDC · Bifrost 허브 · ERC-3643 화이트리스트 · 상환 ASYNC — TrancheSDK.create({ set: 'c' }) (0x0000000100000005)
시나리오 D멀티체인 · 로빈후드 QQQ 미러링 8종목 바스켓(ETF형) · 허브 49088 + 스포크 Robinhood 46630 — OMNIFI_SETS.d (0x000000020000000b)
허브 체인Bifrost 테스트베드 (chainId 49088) — 노드 tbed-rpc.thebifrost.dev기본 접속은 SDK 내장 터널 RPC(VPN·env 불필요), 사내망 직결(VPN)은 백업. 퍼블릭 노드는 프리컴파일 미탑재 · https 배포 시 http RPC는 mixed content 차단 → 게이트웨이 필요
체인 레지스트리Bifrost(49088, BFC) · Sepolia(11155111, ETH) · Robinhood 테스트넷(46630, ETH — rpc.testnet.chain.robinhood.com) — OMNIFI_CHAINS 정본, 볼트 주소는 프리컴파일 자동 발견
파우셋 (테스트넷 전용)UniversalFaucet — 허브 0xFf3A…8f05 · Sepolia 0x3775…8DB3 · Robinhood 0x3c1d…67ee (OMNIFI_FAUCETS)
입금 자산 / shareUSDC · oSR (Senior) · oJR (Junior)
정산 주기60분 · 신청 마감 = 회차 종료 20분 전
i컨트랙트 주소는 SDK가 허브 프리컴파일에서 자동 발견합니다 — 프론트엔드가 하드코딩할 주소는 없습니다.

문서 정본: RWA-SDK/docs/USAGE.ko.md · 2026-08-18 테스트베드 라이브 검증 기준

Reference Environment

Environment

Current testbed configuration.

ItemValue
Package@omnifi/sdk (legacy aliases RwaTranche/RwaError kept)
Default productScenario A (productId 0x0000000200000009 — USDC base asset) — the OmniFi.create() default
Scenario AMultichain · USDC · hub 49088 + spoke Sepolia — OMNIFI_SETS.a
Scenario BSingle-chain · JPYC (18dec) · Sepolia — TrancheSDK.create({ set: 'b' }) (0x0000000100000004)
Scenario CSingle-chain · USDC · Bifrost hub · ERC-3643 whitelist · ASYNC redeem — TrancheSDK.create({ set: 'c' }) (0x0000000100000005)
Scenario DMultichain · Robinhood QQQ-mirroring 8-stock basket (ETF-like) · hub 49088 + spoke Robinhood 46630 — OMNIFI_SETS.d (0x000000020000000b)
Hub chainBifrost testbed (49088) — node tbed-rpc.thebifrost.dev — default access is the SDK's built-in tunnel RPC (no VPN/env); the internal nodes are backups
Chain registryBifrost (49088, BFC) · Sepolia (11155111, ETH) · Robinhood testnet (46630, ETH — rpc.testnet.chain.robinhood.com) — OMNIFI_CHAINS; vault addresses auto-discovered from precompiles
Faucets (testnet-only)UniversalFaucet — hub 0xFf3A…8f05 · Sepolia 0x3775…8DB3 · Robinhood 0x3c1d…67ee (OMNIFI_FAUCETS)
Asset / sharesUSDC · oSR (Senior) · oJR (Junior)
Settlement cycle60 min · orders close 20 min before cycle end

Canonical source: RWA-SDK/docs/USAGE.ko.md · verified live 2026-08-18

OmniFi SDK Docs · @omnifi/sdk