@affluent-org/sdk 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/Refactoring.md +0 -548
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@affluent-org/sdk",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "affluent-sdk",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
package/Refactoring.md DELETED
@@ -1,548 +0,0 @@
1
- # Factorial SDK Refactoring Plan
2
-
3
- ## 현재 핵심 문제
4
-
5
- 하나의 클래스/파일이 여러 성격의 책임을 동시에 지고 있다.
6
-
7
- | 파일 | 라인 수 | 섞여 있는 것 |
8
- |------|---------|-------------|
9
- | `contracts/vault/strategy-vault/index.ts` | 4,614 | Codec + Query + Action + Computation |
10
- | `pool.ts` | 2,895 | Query + Action + Oracle + Tracker + Flow |
11
- | `strategy_vault/base.ts` | 2,637 | Query + Action + Oracle + Computation |
12
- | `share-vault.ts` | 1,213 | Query + Action + Tracker + Flow |
13
- | `contracts/core/pool/index.ts` | 409 | Codec + Query + Action + Computation |
14
-
15
- ---
16
-
17
- ## 기능 레이어 정의
18
-
19
- SDK가 하는 모든 일은 다음 5개 레이어로 분류된다.
20
-
21
- ```
22
- ┌─────────────────────────────────────────────────┐
23
- │ Flow │
24
- │ 다단계 흐름 조율 (조합 레이어) │
25
- ├────────┬────────┬────────┬─────────────────────┤
26
- │ Query │ Oracle │Compute │ Tracker │
27
- │온체인 │외부 │로컬 │ 온체인 │
28
- │읽기 │데이터 │연산 │ 변화 감시 │
29
- ├────────┴────────┴────────┴─────────────────────┤
30
- │ Codec │
31
- │ Cell ↔ TS 양방향 변환 │
32
- └─────────────────────────────────────────────────┘
33
- ```
34
-
35
- | 레이어 | 정의 | I/O | 의존 |
36
- |--------|------|-----|------|
37
- | **Codec** | Cell ↔ TypeScript 객체 양방향 변환. 메시지 빌드(`create*MsgBody` → Cell) 포함 | 없음 | 없음 |
38
- | **Query** | 온체인 상태 읽기 (get method 호출) | provider | Codec |
39
- | **Oracle** | 외부 데이터 수집 (가격 피드 등) | 외부 API | Codec |
40
- | **Computation** | 이미 가져온 데이터로 로컬 계산 | 없음 | 없음 |
41
- | **Tracker** | 온체인 트랜잭션 전파 추적, 결과 대기 | provider | Codec |
42
- | **Flow** | 위 레이어들의 조합. 고수준 사용자 동작 단위 | 전부 | 전부 |
43
-
44
- > **Action 레이어 제거**: 기존에 Codec의 `create*MsgBody`(→ Cell)를 `{ to, value, body }` 로 감싸는 Action 레이어가 있었으나, 모든 함수가 동일한 래핑만 수행하므로 불필요한 추상화로 판단하여 제거. 호출하는 쪽(Flow 또는 사용자)에서 직접 조립한다:
45
- > ```ts
46
- > const body = createSetOwnerAddressMsgBody(newOwner);
47
- > await sender.send({ to: vault.address, value: toNano("0.1"), body });
48
- > ```
49
-
50
- ---
51
-
52
- ## 3레벨 아키텍처
53
-
54
- 레이어를 분리하려면 **2분류(libs + services)로는 부족**하다. Query/Action이 두 수준에 걸쳐 있고, Oracle/Tracker는 특정 도메인에 속하지 않기 때문이다.
55
-
56
- | 레이어 | I/O | 범위 | 소속 레벨 |
57
- |--------|-----|------|----------|
58
- | Codec | 없음 | 컨트랙트별 | contracts/ |
59
- | Computation | 없음 | 컨트랙트별 + 범용 | contracts/ + core/ |
60
- | Query | provider | 컨트랙트별 | contracts/ |
61
- | Oracle | 외부 API | **도메인 횡단** | core/ |
62
- | Tracker | provider + 시간 | **도메인 횡단** | core/ |
63
- | Flow | 전부 | 도메인별 | services/ |
64
-
65
- ### 3개 레벨 구조
66
-
67
- ```
68
- ┌──────────────────────────────────────────────┐
69
- │ services/ (도메인별) │
70
- │ Flow: 고수준 API, 레이어 조합 │
71
- │ pool/ share-vault/ strategy-vault/ rfq/ │
72
- ├──────────────────────────────────────────────┤
73
- │ core/ (도메인 횡단) │
74
- │ Oracle: 외부 데이터 수집 │
75
- │ Tracker: Tx 추적, Step 실행 │
76
- │ ContractOpener: 컨트랙트 열기 + 캐시 │
77
- │ Cache: TTL 캐시 │
78
- │ RiskCalculator: 범용 Computation │
79
- ├──────────────────────────────────────────────┤
80
- │ contracts/ (컨트랙트별) │
81
- │ Codec: Cell ↔ TS │
82
- │ Computation: 순수 계산 │
83
- │ Query + Action: 단일 컨트랙트 get/send │
84
- │ Constants, Types │
85
- └──────────────────────────────────────────────┘
86
- ```
87
-
88
- ### 의존 방향
89
-
90
- ```
91
- services/ ──→ core/ ──→ contracts/
92
- │ ↑
93
- └───────────────────────┘
94
- ```
95
-
96
- **단방향만 허용.** contracts/가 core/나 services/를 import하면 안 된다. core/가 services/를 import하면 안 된다.
97
-
98
- ---
99
-
100
- ## 레벨 1: contracts/ — 컨트랙트별, 바닥 레이어
101
-
102
- ### 역할
103
-
104
- 한 컨트랙트의 인터페이스를 정의한다. **다른 컨트랙트를 모른다.**
105
-
106
- 포함 레이어: Codec, Computation, Query(단일), Constants, Types
107
-
108
- ### 레이어별 경계
109
-
110
- | 레이어 | 받는 것 | 반환하는 것 | 의존 |
111
- |--------|---------|-----------|------|
112
- | Codec | Cell/Slice 또는 TS 객체 | TS 객체 또는 Cell | 없음 |
113
- | Computation | TS 객체 (이미 파싱된 상태) | TS 객체 (계산 결과) | Codec의 타입만 |
114
- | Query | provider + 주소/파라미터 | 파싱된 TS 객체 | Codec (파싱에 사용) |
115
-
116
- ### 파일 분리 구조
117
-
118
- ```
119
- contracts/<domain>/<contract>/
120
- ├── codec.ts ← Codec: 직렬화 + 파싱 + DictionaryValues (Cell ↔ TS 전부)
121
- ├── computation.ts ← Computation: 시뮬레이션, Gas 계산, 상태 변환
122
- ├── constants.ts ← Op, ErrorCodes, Gas
123
- ├── type.ts ← 상태/설정 타입 정의
124
- └── index.ts ← Contract 클래스 (Query만)
125
- ```
126
-
127
- > **dictionary.ts 제거**: DictionaryValues는 codec.ts 안에 포함. 단순한 serialize/parse 리스트이므로 별도 파일 불필요.
128
-
129
- ### index.ts (Contract 클래스)의 최종 역할
130
-
131
- - **Query**: `get*` 메서드 — provider를 통해 온체인 데이터를 읽고, `codec.ts`로 파싱하여 반환
132
-
133
- Contract 클래스가 Codec과 Computation을 **import해서 사용**하되 **소유하지 않는** 구조.
134
-
135
- 메시지 빌드는 Codec의 `create*MsgBody` 함수를 직접 사용:
136
- ```ts
137
- import { createDepositPayload } from "./codec";
138
- const body = createDepositPayload(responseAddress, oracleParams);
139
- await sender.send({ to: vault.address, value: toNano("0.5"), body });
140
- ```
141
-
142
- ### 적용 대상
143
-
144
- | 컨트랙트 | Codec 추출 대상 | Computation 추출 대상 |
145
- |---------|----------------|---------------------|
146
- | Pool | `parsePoolData`, `createSupplyPayload`, `createWithdrawMsgBody` 등 | `simulateAccrueInterest`, `calculateGasFee` |
147
- | Account | `parseAccountData`, `accountConfigToCell` | `convertShareToAmount`, `applyDelta`, `haveBorrow`, `haveAssets` |
148
- | ShareVault | `parseVaultData`, config 직렬화 | `calculateGasFee` |
149
- | StrategyVault | 4,614줄 중 대부분 — parse/create 전체 | Gas 계산, fee accrual |
150
- | RFQAuction | `parseRFQStorage`, 메시지 빌더 | `computeBidReserveFee`, `computeSellReserveFee` |
151
- | RFQBatch | `parseStorage`, 메시지 빌더 | `computeOrderReserveFee` |
152
-
153
- ### _parse_temp 폴더 처리
154
-
155
- `utils/_parse_temp/` (5,343줄)의 파싱 로직을 각 Contract의 `codec.ts`로 흡수하고 폴더 삭제.
156
-
157
- ### Tx 메시지 Codec
158
-
159
- 현재 `utils/parser.ts`에 범용으로 존재하는 Tx 메시지 파싱을 Contract별 `codec.ts`로 분산하고, 범용 dispatch 함수만 남긴다.
160
-
161
- ---
162
-
163
- ## 레벨 2: core/ — 도메인 횡단, 중간 레이어
164
-
165
- ### 역할
166
-
167
- 여러 도메인이 공유하는 I/O 인프라를 제공한다. **특정 도메인에 속하지 않는다.**
168
-
169
- 포함 레이어: Oracle, Tracker, ContractOpener, Cache, 범용 Computation
170
-
171
- ### 레이어별 경계
172
-
173
- | 모듈 | 받는 것 | 반환하는 것 | 의존 |
174
- |------|---------|-----------|------|
175
- | Oracle | 자산 주소 목록 + oracle config | 가격 데이터, oracle params (Cell) | contracts/ Codec (Cell 빌드), 외부 API (Redstone) |
176
- | Tracker | provider + 탐색 조건 (주소, queryId, step 목록) | 발견된 트랜잭션, 완료 상태 | contracts/ Codec (tx 파싱), provider (폴링) |
177
- | ContractOpener | TonClient + Contract 클래스 + 주소 | OpenedContract (캐시된 인스턴스) | contracts/ (Contract 타입), Cache |
178
- | Cache | 캐시 키 + 값 | 캐시된 값 | 없음 |
179
- | RiskCalculator | 파싱된 account/pool 상태 + 가격 | risk ratio, max borrow/withdraw | contracts/ 타입만 |
180
-
181
- ### 파일 구조
182
-
183
- ```
184
- core/
185
- ├── oracle/
186
- │ ├── redstone.ts ← Redstone 연동
187
- │ ├── oracle-params.ts ← oracle params 빌드 (현 oracle-v2.ts)
188
- │ └── type.ts ← AddressBucket, OracleParamsResult 등
189
- ├── tracker/
190
- │ ├── tx-finder.ts ← 트랜잭션 탐색 (현 utils/tracer.ts)
191
- │ ├── step-runner.ts ← Step 순차 실행 + 콜백
192
- │ ├── seqno-waiter.ts ← wallet seqno 폴링 대기
193
- │ └── type.ts ← TxStep, StepCallback 등
194
- ├── contract-opener.ts ← Contract 열기 + 캐시 (현 ServiceBaseV1.open/getByContract)
195
- ├── cache.ts ← ContractCache + withCache (현 common/cache.ts)
196
- ├── risk-calculator/ ← 범용 Computation (현 utils/risk_calculator/)
197
- └── type.ts ← 공용 타입 (Maybe, AddressLike, AddressInput)
198
- ```
199
-
200
- ### 현재 코드에서 추출할 위치
201
-
202
- | core/ 모듈 | 현재 위치 | 추출 방법 |
203
- |------------|----------|----------|
204
- | oracle | `oracle/oracle-v2.ts` + `PoolV1` 내 oracle 메서드 + `StrategyVaultBase` 내 oracle 메서드 | oracle-v2.ts를 core/로 이동, 서비스 내 인라인 oracle 로직을 core/oracle 호출로 교체 |
205
- | tracker | `PoolV1.findAndCallback` + `ShareVaultV1.buildSupplySteps/waitSupplyTx` + `StrategyVaultSteps.processingSteps` + `utils/tracer.ts` | 공통 패턴(step 빌드, step 실행, tx 탐색, polling)을 추출 |
206
- | contract-opener | `ServiceBaseV1.open()`, `getByContract()`, `contractCache` | ServiceBaseV1에서 분리, 주입 가능한 객체로 |
207
- | cache | `common/cache.ts` | 위치 이동 |
208
- | risk-calculator | `utils/risk_calculator/` | 위치 이동 |
209
-
210
- ### ServiceBaseV1 해체
211
-
212
- 현재 ServiceBaseV1이 제공하는 기능을 core/ 모듈로 분산:
213
-
214
- | 기능 | 현재 (ServiceBaseV1) | 변경 (core/) |
215
- |------|---------------------|-------------|
216
- | Contract 캐시 + 열기 | `open()`, `getByContract()` | `core/contract-opener.ts` |
217
- | 네트워크 설정 | `contracts`, `network` | 생성자 주입 설정 타입 |
218
- | Asset Type 캐시 | `static assetTypes` | `core/contract-opener.ts` 인스턴스 레벨 |
219
- | Wallet seqno 대기 | `waitWalletSeq()` | `core/tracker/seqno-waiter.ts` |
220
- | WTON 배포 | `deployWTONWallet()` | `services/` 레벨 Flow |
221
-
222
- ---
223
-
224
- ## 레벨 3: services/ — 도메인별, 최상위 레이어
225
-
226
- ### 역할
227
-
228
- 사용자가 호출하는 고수준 API를 제공한다. contracts/와 core/를 **조합**한다.
229
-
230
- 포함 레이어: Flow (Query + Action + Oracle + Tracker 조합)
231
-
232
- ### 레이어별 경계
233
-
234
- | 레이어 | 받는 것 | 반환하는 것 | 의존 |
235
- |--------|---------|-----------|------|
236
- | Flow | 사용자 파라미터 (sender, 금액, 주소 등) | 트랜잭션 결과, 추적 결과 | contracts/ (Query, Action, Codec) + core/ (Oracle, Tracker, ContractOpener) |
237
-
238
- **실제 전송은 Flow에서 발생:**
239
- ```ts
240
- // services/pool/supply.ts (Flow)
241
- const body = createSupplyPayload(params); // Codec: Cell 생성
242
- await sender.send({ to: pool.address, value: toNano("0.5"), body }); // Flow: 전송
243
- ```
244
-
245
- ### 서비스 내부 분리 판단
246
-
247
- 서비스 내부를 더 쪼갤지는 **크기로 판단**한다.
248
-
249
- | 서비스 | 현재 크기 | 분리 여부 | 근거 |
250
- |--------|----------|----------|------|
251
- | Pool | 2,895줄 | 분리 필요 | supply/withdraw/borrow/repay/liquidate 5개 도메인 액션 + 가격/리스크 조회 |
252
- | ShareVault | 1,213줄 | 분리 필요 | 버전 분기(V1/V2) + 매니저 액션 |
253
- | StrategyVault | 2,637 + 498줄 | 분리 필요 | deposit/withdraw/queue/owner/config 5개 도메인 액션 |
254
- | RFQAuction | 작음 | 단일 파일 | Flow가 단순 |
255
- | RFQBatch | 작음 | 단일 파일 | Flow가 단순 |
256
-
257
- ### 큰 서비스 분리 구조
258
-
259
- ```
260
- services/<domain>/
261
- ├── index.ts ← Flow: 고수준 API (조합 포인트)
262
- ├── supply.ts ← Flow: supply 흐름 (Action + Tracker 조합)
263
- ├── withdraw.ts ← Flow: withdraw 흐름
264
- ├── ... ← 도메인별 추가 흐름
265
- └── queries.ts ← 서비스 레벨 조회 (여러 contracts/ Query 조합)
266
- ```
267
-
268
- 각 파일 내부에서 contracts/와 core/를 import해서 조합한다. **파일 간 import는 index.ts를 통해서만.**
269
-
270
- ### 조합 예시: supply 흐름의 의존 관계
271
-
272
- ```
273
- services/pool/supply.ts (Flow)
274
- ├── contracts/jetton/ Query: wallet 주소 조회
275
- ├── contracts/core/pool/ Query: pool 데이터, Codec: supply Cell 빌드, Computation: gas 계산
276
- ├── contracts/core/account/ Query: account 주소
277
- ├── core/oracle/ Oracle: 가격 데이터 수집
278
- ├── core/tracker/ Tracker: tx 추적, step 실행
279
- └── sender.send() Flow에서 직접 전송 (Codec은 Cell만 생성)
280
- ```
281
-
282
- ### 작은 서비스 단일 파일 구조
283
-
284
- ```
285
- services/rfq-auction/
286
- └── index.ts ← Flow + 조회 전부 포함
287
- ```
288
-
289
- ---
290
-
291
- ## 반복 패턴 추출
292
-
293
- 3회 이상 반복이 확인된 패턴만 추출한다.
294
-
295
- ### Dictionary → Record 변환 (5회 반복)
296
-
297
- Pool, Account, ShareVault, StrategyVault, RFQBatch에서 동일한 Dictionary → Record 변환 패턴 반복.
298
- `contracts/` 레벨 공통 Codec 유틸로 추출.
299
-
300
- ### 트랜잭션 Step 빌드 + 실행 (3회 반복)
301
-
302
- PoolV1, ShareVaultV1, StrategyVaultSteps에서 동일한 step 배열 빌드 → 순차 실행 → 콜백 패턴 반복.
303
- `core/tracker/step-runner.ts`로 추출.
304
-
305
- ### ~~Message 빌더 반환 타입 (10회+ 반복)~~ → 제거됨
306
-
307
- Action 레이어를 제거했으므로 `TxMessage` 래핑 패턴도 불필요. Codec이 `Cell`을 반환하고, 호출 측에서 `{ to, value, body }` 인라인 조립.
308
-
309
- ### Address 변환 (4회 반복)
310
-
311
- `toAddress()` 헬퍼가 `contracts/common/utils.ts`, `pool.ts`, `share-vault.ts`, `strategy_vault/base.ts`에 중복.
312
- `core/type.ts`로 통합.
313
-
314
- ---
315
-
316
- ## 타입 정리
317
-
318
- ### 중복 타입 통합
319
-
320
- | 타입 | 중복 위치 | 통합 위치 |
321
- |------|----------|----------|
322
- | `Maybe<T>` | `types/pool.ts`, `contracts/common/type.ts` | `core/type.ts` |
323
- | `AddressLike` | `contracts/common/type.ts`, 여러 파일 인라인 | `core/type.ts` |
324
-
325
- ### 대형 Config 타입 분할
326
-
327
- `StrategyVaultConfig` (50+ 필드)를 논리적 하위 타입으로 분할: Ownership, State, FeeConfig, QueueConfig 등.
328
-
329
- ### Cell | ParsedType 모호성 해결
330
-
331
- `irmConfig: Cell | JumpIRMConfig` 같은 union을 Raw 타입과 Parsed 타입으로 명확히 분리.
332
-
333
- ### 네이밍 규칙 확립
334
-
335
- | 접미사 | 의미 |
336
- |--------|------|
337
- | `*Payload` | Jetton forward에 실리는 데이터 (Codec 산출물) |
338
- | `*MsgBody` | 직접 전송하는 메시지 본문 (Codec 산출물) |
339
- | `*Params` | SDK 함수에 전달하는 TypeScript 파라미터 (Codec 입력) |
340
-
341
- ### 오타 수정
342
-
343
- - `TansferOutActionParams` → `TransferOutActionParams`
344
- - `traceActionNotificaitonTx` → `traceActionNotificationTx`
345
- - `LiquidateionNotificationFee` → `LiquidationNotificationFee`
346
-
347
- ---
348
-
349
- ## 정리 작업
350
-
351
- - `utils/_parse_temp/` 폴더 삭제 (contracts/ codec.ts로 흡수 완료)
352
- - console.log 제거 (`utils/parser.ts`, `share-vault.ts`)
353
- - 주석 처리된 dead code 제거 (`utils/parser.ts`, `share-vault.ts`)
354
-
355
- ---
356
-
357
- ## 최종 디렉토리 구조
358
-
359
- ```
360
- src/
361
- ├── contracts/ ← 레벨 1: 컨트랙트별 (다른 컨트랙트를 모름)
362
- │ ├── core/
363
- │ │ ├── pool/
364
- │ │ │ ├── codec.ts ← Codec + DictionaryValues
365
- │ │ │ ├── computation.ts ← Computation: 시뮬레이션, Gas
366
- │ │ │ ├── constants.ts ← Op, ErrorCodes, Gas
367
- │ │ │ ├── type.ts ← 타입 정의
368
- │ │ │ └── index.ts ← Contract 클래스 (Query)
369
- │ │ └── account/
370
- │ │ ├── codec.ts
371
- │ │ ├── computation.ts ← 지분 변환, delta
372
- │ │ ├── constants.ts
373
- │ │ ├── type.ts
374
- │ │ └── index.ts
375
- │ ├── vault/
376
- │ │ ├── share-vault/
377
- │ │ │ ├── codec.ts ← Codec + DictionaryValues
378
- │ │ │ ├── computation.ts
379
- │ │ │ ├── constants.ts
380
- │ │ │ ├── type.ts
381
- │ │ │ └── index.ts
382
- │ │ └── strategy-vault/ ← ✅ codec 분리 완료
383
- │ │ ├── codec.ts ← Codec + DictionaryValues (#region 섹션)
384
- │ │ ├── computation.ts
385
- │ │ ├── constants.ts
386
- │ │ ├── type.ts ← 분할된 Config 하위 타입
387
- │ │ └── index.ts
388
- │ ├── rfq/
389
- │ │ ├── auction/ ← 동일 구조
390
- │ │ ├── batch/
391
- │ │ └── event-emitter/
392
- │ ├── jetton/
393
- │ ├── factory/
394
- │ └── wton/
395
-
396
- ├── core/ ← 레벨 2: 도메인 횡단 (특정 도메인에 속하지 않음)
397
- │ ├── oracle/
398
- │ │ ├── redstone.ts ← Redstone 연동
399
- │ │ ├── oracle-params.ts ← oracle params 빌드
400
- │ │ └── type.ts
401
- │ ├── tracker/
402
- │ │ ├── tx-finder.ts ← 트랜잭션 탐색
403
- │ │ ├── step-runner.ts ← Step 순차 실행 + 콜백
404
- │ │ ├── seqno-waiter.ts ← wallet seqno 폴링 대기
405
- │ │ └── type.ts ← TxStep, StepCallback 등
406
- │ ├── risk-calculator/ ← 범용 Computation
407
- │ ├── contract-opener.ts ← Contract 열기 + 캐시
408
- │ ├── cache.ts ← ContractCache + withCache
409
- │ └── type.ts ← Maybe, AddressLike, toAddress
410
-
411
- ├── services/ ← 레벨 3: 도메인별 (contracts/ + core/ 조합)
412
- │ ├── pool/
413
- │ │ ├── index.ts ← Flow: 고수준 API
414
- │ │ ├── supply.ts ← Flow: supply 흐름
415
- │ │ ├── withdraw.ts ← Flow: withdraw 흐름
416
- │ │ ├── borrow.ts ← Flow: borrow 흐름
417
- │ │ ├── repay.ts ← Flow: repay 흐름
418
- │ │ ├── liquidate.ts ← Flow: liquidate 흐름
419
- │ │ └── queries.ts ← 서비스 레벨 조회 (가격, 리스크 등)
420
- │ ├── share-vault/
421
- │ │ ├── index.ts ← Flow
422
- │ │ ├── supply.ts
423
- │ │ ├── withdraw.ts
424
- │ │ ├── manage.ts ← 매니저 액션 (supplyToPool, withdrawFromPool, setTargetWeight)
425
- │ │ └── queries.ts
426
- │ ├── strategy-vault/
427
- │ │ ├── index.ts ← Flow
428
- │ │ ├── deposit.ts
429
- │ │ ├── withdraw.ts
430
- │ │ ├── queue.ts ← deposit/withdraw queue
431
- │ │ ├── owner.ts ← owner/guardian/manager 설정
432
- │ │ └── queries.ts
433
- │ ├── rfq-auction/
434
- │ │ └── index.ts ← Flow (단일 파일)
435
- │ └── rfq-batch/
436
- │ └── index.ts ← Flow (단일 파일)
437
-
438
- ├── types/ ← 공개 타입
439
- ├── constants/ ← 전역 상수
440
- ├── _compiled/ ← 컴파일된 바이너리
441
- └── index.ts ← 배럴 export
442
- ```
443
-
444
- ---
445
-
446
- ## 실행 순서
447
-
448
- | 순서 | 내용 | 대상 레벨 | 상태 |
449
- |------|------|----------|------|
450
- | 1 | 정리 (console.log, dead code, 오타) | 전체 | |
451
- | 2 | 타입 중복 제거, 네이밍 정리 | 전체 | |
452
- | 3 | contracts/ Codec 분리 | contracts/ | **strategy-vault ✅** |
453
- | 4 | contracts/ Computation 분리 | contracts/ | |
454
- | 5 | contracts/ index.ts 정리 (Query만 잔류) | contracts/ | |
455
- | 6 | core/ 모듈 추출 (Oracle, Tracker, ContractOpener) | core/ | |
456
- | 7 | services/ 재구성 (상속 제거, Flow 조합) | services/ | |
457
-
458
- 아래에서 위로. contracts/ (I/O 없는 Codec, Computation) → core/ (도메인 횡단 인프라) → services/ (Flow 조합).
459
-
460
- ---
461
-
462
- ## 진행 기록
463
-
464
- ### strategy-vault Codec 분리 (완료)
465
-
466
- **변경 내용:**
467
- - 28개 파일 (`codec/` 디렉토리) + `parser.ts` + `dictionary.ts` → 단일 `codec.ts`로 병합 (~1270줄)
468
- - `#region` 섹션으로 구분: Dictionary Values, Storage, Utility, Message-Owner, Message-Manager, Message-User
469
- - `action/` 디렉토리 전체 삭제 — `{ to, value, body }` 래핑만 하는 함수들은 불필요한 추상화
470
- - `serializer.ts` (레거시) 삭제
471
-
472
- **결과 구조:**
473
- ```
474
- contracts/vault/strategy-vault/
475
- ├── codec.ts ← 1270줄, #region 섹션
476
- ├── constants.ts
477
- ├── type.ts
478
- └── index.ts ← StrategyVault 클래스 (Query + static re-exports)
479
- ```
480
-
481
- **설계 판단:**
482
- - codec은 단순 serialize/parse 리스트이므로 파일이 길어도 문제 없음. 한번 만들면 고정이고, 수정해도 단일 액션
483
- - 파일 분할 기준은 "독립적으로 변경 가능한 단위"이지 "줄 수"가 아님
484
- - DictionaryValues도 codec 안에 포함 — 별도 파일 불필요
485
-
486
- ---
487
-
488
- ### CompositeOracle 리팩토링 (완료)
489
-
490
- **문제점:**
491
- - `strategy-vault/oracle.ts`에 가격 계산 로직이 중복 존재 (487줄)
492
- - `composite-oracle/`와 동일한 가격 계산 함수들이 분산되어 있음
493
- - `getOracleParams`(온체인 Cell 생성)와 `CompositeOracle`(오프체인 가격 계산)이 같은 데이터를 각각 따로 fetch
494
-
495
- **핵심 원칙: I/O와 Computation 분리**
496
- ```
497
- ┌─────────────────────────────────────────────────────────┐
498
- │ services/ 레이어 │
499
- ├─────────────────────────────────────────────────────────┤
500
- │ CompositeOracle (가격 계산) StrategyVault (트랜잭션) │
501
- │ │ │ │
502
- │ ▼ ▼ │
503
- │ ┌─────────────────────────────────────────────┐ │
504
- │ │ getOracleContext() │ │
505
- │ │ (공유 데이터 fetch) │ │
506
- │ └─────────────────────────────────────────────┘ │
507
- │ │ │ │
508
- │ ▼ ▼ │
509
- │ compute() ← 순수 함수 getOracleParamsV2() │
510
- │ (가격 계산) (Cell 생성) │
511
- └─────────────────────────────────────────────────────────┘
512
- ```
513
-
514
- **변경 내용:**
515
-
516
- 1. **getOracleContext() 공유 메서드 생성** (`composite-oracle/fetcher.ts`)
517
- - vault 데이터, oracle config, 자산 목록, 포지션 등을 한 번에 fetch
518
- - On-chain Cell 생성과 Off-chain 가격 계산 모두 동일 context 사용
519
-
520
- 2. **strategy-vault/oracle.ts 대폭 축소** (487줄 → 107줄)
521
- - 중복된 가격 계산 함수 모두 제거: `getAssetPrice`, `calcVaultPrice`, `computeAssetPrices` 등
522
- - `getOracleParamsV2`만 남김 — CompositeOracle의 `getOracleContext()` 사용
523
-
524
- 3. **StrategyVaultV1 가격 메서드 위임** (`services/strategy-vault/index.ts`)
525
- - `getVaultPrice()`, `getTotalValue()`, `getAllAssetPrices()` → CompositeOracle 호출로 변경
526
-
527
- **결과 구조:**
528
- ```
529
- services/
530
- ├── composite-oracle/
531
- │ ├── fetcher.ts ← getOracleContext() 공유 메서드 추가
532
- │ ├── computation.ts ← 순수 가격 계산 (I/O 없음)
533
- │ └── index.ts ← fetchAll(), compute(), static helpers
534
- ├── strategy-vault/
535
- │ ├── oracle.ts ← 107줄로 축소 (getOracleParamsV2만)
536
- │ └── index.ts ← 가격 메서드는 CompositeOracle 위임
537
- ```
538
-
539
- **설계 판단:**
540
- - **"Fetch once, compute multiple times"**: 데이터는 한 번만 fetch하고, 계산은 여러 번 재사용
541
- - **On-chain vs Off-chain 분리**:
542
- - On-chain: `getOracleParamsV2()` → Cell 생성 (트랜잭션에 사용)
543
- - Off-chain: `compute()` → 가격 계산 (조회에 사용)
544
- - **Static 메서드 제공**: 캐시된 input으로 재계산 가능 (`getVaultPriceFromInput`, `getTotalValueFromInput`)
545
-
546
- **테스트 결과:**
547
- - mainnet 테스트 7개 항목 모두 통과
548
- - fork 테스트 9개 항목 모두 통과