@bitpal/checkout 0.3.0 → 0.6.0

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.
package/dist/index.d.ts CHANGED
@@ -3,13 +3,17 @@
3
3
  */
4
4
  interface BitPalConfig {
5
5
  /**
6
- * API 키. prefix 가 mode 를 결정합니다:
6
+ * API 키(서버 전용, secret). prefix 가 mode 를 결정합니다:
7
7
  * - `bp_test_...` → TEST mode (testnet 또는 local anvil)
8
8
  * - `bp_live_...` → LIVE mode (mainnet)
9
9
  *
10
10
  * BitPal 콘솔 → Developers → API Keys 에서 발급.
11
+ *
12
+ * **선택**: createSession/listSessions/products 등 서버 메서드는 필수. 그러나 buyer-facing 공개 메서드
13
+ * (getPublicSession/getStatus/issueDepositAddress)는 인증 불요(session_token 기반)이므로 브라우저에서
14
+ * apiKey 없이 쓸 수 있다 — 절대 secret 키를 브라우저에 노출하지 말 것.
11
15
  */
12
- apiKey: string;
16
+ apiKey?: string;
13
17
  /**
14
18
  * BitPal API 기본 URL. 환경별로 다릅니다:
15
19
  * - production: `https://api.bitpal.io` (기본값) — 실제 testnet/mainnet 컨트랙트
@@ -21,23 +25,48 @@ interface BitPalConfig {
21
25
  /** 요청 타임아웃 (ms, 기본값: 30000) */
22
26
  timeout?: number;
23
27
  }
28
+ /** 응답/정규화된 line item — amount 는 항상 atomic μUSD 정수. */
24
29
  interface LineItem {
25
30
  name: string;
26
- /**
27
- * Atomic μUSDC 정수 문자열 (USDC/USDT 6 decimals).
28
- * $1 = "1000000", $29 = "29000000".
29
- * decimal 표기는 거부된다 — `toAtomicUSDC('29.00')` 헬퍼 사용 권장.
30
- */
31
+ /** Atomic μUSD 정수 문자열($1="1000000", $29="29000000"). */
31
32
  amount: string;
32
33
  currency: string;
33
34
  quantity?: number;
34
35
  }
36
+ /**
37
+ * 세션 생성 입력용 line item. 금액은 둘 중 **하나**:
38
+ * - `amount`(권장): 사람 표기 USD 문자열(예 "29", "0.5", "29.00"). decimal 신경 쓸 필요 없음.
39
+ * ※ 금액은 **USD 가격**이다(체인/토큰 decimal 무관). 토큰(USDC 6dp / BNB USDT 18dp)별 스케일은 발급 시 서버가 처리.
40
+ * - `amount_atomic`: 이미 raw μUSD 정수 문자열($1="1000000")인 경우(고급/기존 코드).
41
+ * 둘 다 지정하거나 둘 다 생략하면 SDK 가 에러를 throw 한다.
42
+ */
43
+ interface LineItemInput {
44
+ name: string;
45
+ currency: string;
46
+ quantity?: number;
47
+ /** 사람 표기 USD 금액(예 "29", "0.5") — 권장. amount_atomic 과 상호배타. */
48
+ amount?: string;
49
+ /** raw μUSD 정수($1="1000000") — 고급/기존. amount 와 상호배타. */
50
+ amount_atomic?: string;
51
+ }
52
+ interface PriceLineItem {
53
+ /** price_... — bitpal.checkout.prices.create()로 만든 가격 */
54
+ price_id: string;
55
+ quantity?: number;
56
+ }
57
+ type CheckoutLineItemInput = LineItemInput | PriceLineItem;
35
58
  interface CreateSessionParams {
36
- line_items: LineItem[];
59
+ line_items: CheckoutLineItemInput[];
37
60
  /** 고객 지갑 주소 (선택) */
38
61
  payer_wallet?: string;
39
- /** 결제 체인 (예: eip155:8453) */
62
+ /** 결제 체인 (예: eip155:8453). 단일 고정 — allowed_pay_chains와 상호 배타. */
40
63
  pay_chain?: string;
64
+ /**
65
+ * 허용 결제 체인 목록 (CAIP-2). 구매자가 이 중에서 선택하며, 하나뿐이면 자동 선택된다.
66
+ * pay_chain(단일 고정)과 **상호 배타** — 동시 지정 시 SDK가 에러를 throw한다.
67
+ * 예: ['eip155:84532', 'eip155:11155420', 'eip155:80002', 'eip155:421614']
68
+ */
69
+ allowed_pay_chains?: string[];
41
70
  /** 결제 자산 (예: USDC) */
42
71
  pay_asset?: string;
43
72
  /** 허용 오차 (%, 기본값: 2.00) */
@@ -67,12 +96,8 @@ interface CheckoutSession {
67
96
  settled_at: string | null;
68
97
  tx_hash: string | null;
69
98
  created_at: string;
70
- /** 'hosted' | 'external' — 결제 경로 구분 */
99
+ /** 'hosted' — 결제 경로. 안2 는 hosted deposit-address 단일 경로. */
71
100
  payment_source?: string;
72
- /** External on-chain 결제 검증 기록 목록 */
73
- payment_observations?: PaymentObservation[];
74
- /** External/gasless checkout payment config supplied by BitPal API. */
75
- external_payment_config?: ExternalPaymentConfig;
76
101
  /** 호스티드 결제 페이지 URL (token 쿼리 포함). backend 응답 그대로 사용 — buyer를 이 URL로 redirect. */
77
102
  checkout_url?: string;
78
103
  /** 1회용 session token. `checkout_url`에 이미 query로 박혀 있어 별도 사용 불필요. */
@@ -80,119 +105,99 @@ interface CheckoutSession {
80
105
  /** `checkout_url`의 별칭 (backwards compat). buyer redirect 시 이 필드 또는 `checkout_url` 사용. */
81
106
  url: string;
82
107
  }
83
- interface ExternalPaymentConfig {
84
- chain: string;
85
- chain_id: string;
86
- payment_id: string;
87
- escrow_contract_address: string | null;
88
- token_address: string | null;
89
- merchant_wallet: string;
90
- amount: string;
91
- fee_amount: string;
92
- reserve_amount: string;
93
- asset: string;
108
+ /**
109
+ * 안2 결제 옵션(chain×token). `/public` 이 서버 권위로 내려주며, buyer 가 하나를 골라
110
+ * `issueDepositAddress({ chain, token })` 로 입금주소를 발급받는다. 단일-자산 세션은 1개.
111
+ */
112
+ interface PaymentOption {
113
+ /** CAIP-2 (예: eip155:8453, tron:0x2b6653dc, solana:5eykt4…). 체인 식별의 canonical. */
114
+ caip2: string;
115
+ /** EVM numeric chainId. 비-EVM(Tron/Solana)은 null — 식별은 caip2 사용. */
116
+ chain_id: number | null;
117
+ token_symbol: string;
118
+ /** 토큰 컨트랙트/mint 주소(EVM 0x / Tron base58 / Solana base58 mint). */
119
+ token_address: string;
120
+ /** 토큰 decimals(USDC/USDT=6, BSC-USD=18). atomic↔decimal 변환에 필수 — 6dp 가정 금지. */
94
121
  decimals: number;
95
- supported_methods: Array<'authorization_relay'>;
96
122
  }
97
123
  /**
98
- * CheckoutEscrow.PaymentDeposited 이벤트 단위 검증 기록.
99
- * `GET /v1/checkout/sessions/:id` 응답의 `payment_observations` 배열 원소.
124
+ * `getPublicSession()` (`GET /v1/checkout/sessions/:id/public`) 응답 — 인증 불요(공개).
125
+ * buyer-facing 결제 페이지가 표시/폴링에 쓰는 서버 권위 뷰.
100
126
  */
101
- interface PaymentObservation {
127
+ interface PublicSession {
102
128
  id: string;
103
- tx_hash: string;
104
- chain_id: string;
105
- from_address: string | null;
106
- to_address: string;
107
- /** Atomic μUSDC 정수 문자열 */
108
- amount: string;
109
- /** 'pending' | 'valid' | 'invalid' | 'duplicate' | 'underpaid' | 'overpaid' */
110
- validation_status: string;
111
- /** 'detected' | 'soft_confirmed' | 'final_confirmed' | 'reorg_revoked' */
112
- finality_status: string;
113
- validation_error: string | null;
114
- block_number: number | null;
115
- confirmations: number;
129
+ /** created | awaiting_deposit | deposit_detected | paid_confirmed | swept | unresolved_* | wrong_token | expired ... */
130
+ status: string;
131
+ mode: string | null;
132
+ currency: string;
133
+ /** Atomic 정수 문자열(토큰 decimals 기준). */
134
+ amount_total: string;
135
+ amount_received?: string | null;
136
+ pay_chain: string | null;
137
+ pay_asset: string | null;
138
+ /** 발급된 주문별 forwarder 입금주소(미발급이면 null). */
139
+ deposit_address?: string | null;
140
+ /** 구매자 선택 가능한 결제 옵션(서버 권위). 단일-자산이면 1개. */
141
+ payment_options: PaymentOption[];
142
+ chain_id: number | null;
143
+ token_address: string | null;
144
+ /** 선택된 pay 토큰 decimals(발급 후). amount_total/amount_received atomic 해석에 사용 — 6dp 가정 금지. */
145
+ token_decimals?: number | null;
146
+ tx_hash: string | null;
147
+ release_tx_hash?: string | null;
148
+ expires_at: string | null;
149
+ success_url: string | null;
150
+ cancel_url: string | null;
151
+ fee_amount: string | null;
152
+ net_amount: string | null;
153
+ seller_wallet: string;
154
+ paid_at: string | null;
155
+ settled_at: string | null;
116
156
  created_at: string;
157
+ line_items: LineItem[];
117
158
  }
118
159
  /**
119
- * `submitExternalPayment` 요청 파라미터.
120
- * 검증에 필요한 값은 tx_hash + chain만으로 충분 — payer_wallet, asset 등은 on-chain 이벤트에서 도출.
121
- */
122
- interface SubmitExternalPaymentParams {
123
- /** CheckoutEscrow 입금 tx hash (0x...) */
124
- tx_hash: string;
125
- /** 체인 식별자 (기본값: 'base'). 예: 'base', 'bnb', 'polygon' */
126
- chain?: string;
127
- /** Public session token — buyer 측 제출 시 사용. API key 인증 시 불필요. */
128
- session_token?: string;
129
- }
130
- /**
131
- * `submitExternalPayment` 응답.
160
+ * `issueDepositAddress()` 요청 파라미터.
161
+ * chain/token 은 멀티옵션 세션에서만 필요(단일-자산 세션은 생략). refundAddress 는 필수 —
162
+ * 금액부족/잘못된토큰/만료 시 이 주소로 환불되며, 입금주소에 커밋되어 발급 후 변경 불가.
132
163
  */
133
- interface SubmitExternalPaymentResult {
134
- observation_id: string;
135
- /** 'valid' | 'invalid' | 'underpaid' | 'overpaid' | 'duplicate' */
136
- validation_status: string;
137
- /** 검증 후 세션 상태 */
138
- session_status: string;
139
- /** 입금한 지갑 주소 (on-chain 이벤트에서 도출) */
140
- from_address: string | null;
141
- /** Atomic μUSDC 정수 문자열 */
142
- amount: string;
143
- message: string;
144
- }
145
- interface PayWithAuthorizationParams {
146
- chain?: string;
164
+ interface IssueDepositAddressParams {
165
+ /** 결제 페이지 접근 증명(HMAC). createSession 응답의 session_token. */
147
166
  session_token: string;
148
- /** EIP-3009 TransferWithAuthorization sig (USDC). */
149
- authorization: {
150
- from: string;
151
- validAfter?: string;
152
- validBefore: string;
153
- authNonce: string;
154
- v: number;
155
- r: string;
156
- s: string;
157
- };
158
167
  /**
159
- * Q5 C-01 옵션 2 (SDK v0.2.0): PaymentAuthorization typed-data sig.
160
- * Buyer 가 결제 의도 전체 (paymentId, merchant, amount, fee, reserve, duration) 에 서명.
161
- * gateway 키 탈취 시에도 buyer 의도 밖 결제 생성 차단.
162
- *
163
- * 서명 생성: `buildPaymentAuthTypedData()` helper 또는 viem `signTypedData` 직접 호출.
164
- * Required for SDK v0.2.x+ — gasless lane 모든 호출에 필수. v0.1.x 는 미지원.
168
+ * 환불 주소. 필수. 선택한 체인의 VM 형식이어야 한다:
169
+ * EVM=0x…, Tron=base58(T…), Solana=base58. 결제와 같은 네트워크의 본인 주소.
170
+ * 금액부족/잘못된토큰/만료 시 이 주소로 환불되며, 입금주소에 커밋되어 발급 후 변경 불가.
165
171
  */
166
- payment_auth: {
167
- deadline: string;
168
- duration: string;
169
- v: number;
170
- r: string;
171
- s: string;
172
- };
172
+ refundAddress: string;
173
+ /** 선택 자산의 chain(CAIP-2 또는 short-name). 멀티옵션 세션 필수. */
174
+ chain?: string;
175
+ /** 선택 자산의 token symbol(예: USDC). 멀티옵션 세션 필수. */
176
+ token?: string;
173
177
  }
174
178
  /**
175
- * Q5 C-01 옵션 2: buyer 가 서명할 EIP-712 PaymentAuthorization typed-data 의 입력 인자.
176
- * `buildPaymentAuthTypedData()` 가 이를 받아 viem 호환 객체를 반환.
179
+ * `issueDepositAddress()` 응답 — 이 주소로 정확 금액을 송금하면 watcher 가 감지, keeper 가 정산한다.
177
180
  */
178
- interface PaymentAuthTypedDataArgs {
179
- escrowAddress: string;
180
- chainId: number;
181
- paymentId: string;
182
- payer: string;
183
- merchant: string;
184
- token: string;
185
- amount: string;
181
+ interface DepositAddress {
182
+ sessionId: string;
183
+ chain: string;
184
+ /** 주문별 결정적 입금주소(EVM/Tron=CREATE2 forwarder, Solana=order PDA 의 deposit ATA). */
185
+ depositAddress: string;
186
+ expectedToken: string;
187
+ /** Atomic 정수 문자열. */
188
+ expectedAmount: string;
186
189
  feeAmount: string;
187
- reserveAmount: string;
188
- duration: string;
190
+ refundAddress: string;
191
+ /** Unix seconds — on-chain deadline. */
189
192
  deadline: string;
190
- nonce: string;
193
+ expiresAt: string | null;
191
194
  }
192
- interface CheckoutPaymentResult {
195
+ /**
196
+ * `getStatus()` (`GET /v1/checkout/sessions/:id/status`) 응답 — 경량 폴링용(인증 불요).
197
+ */
198
+ interface SessionStatus {
193
199
  status: string;
194
- tx_hash: string;
195
- message?: string;
200
+ paid_at: string | null;
196
201
  }
197
202
  /**
198
203
  * 수수료 미리보기 응답.
@@ -206,65 +211,16 @@ interface FeePreview {
206
211
  net_amount: string;
207
212
  }
208
213
  /**
209
- * Auto refund 파라미터 — escrow 보관 중(`escrow_status` pending|disputed)일 때 동작.
210
- * 컨트랙트가 buyer에게 직접 토큰 transfer.
211
- *
212
- * `amount` 미지정 시 backend가 잔액 전액(full refund)을 시도. 명시 시 atomic μUSDC.
213
- */
214
- interface RefundSessionParams {
215
- /** Atomic μUSDC 정수 문자열. 미지정 시 전액. */
216
- amount?: string;
217
- /** 환불 사유 코드 (선택, 머천트 대시보드/audit log 분류용) */
218
- reason?: string;
219
- /** 환불 사유 상세 (선택, 자유 텍스트) */
220
- reason_detail?: string;
221
- }
222
- interface RefundSessionResult {
223
- refunded: boolean;
224
- refundId: string;
225
- /** Atomic μUSDC 정수 문자열 */
226
- amount: string;
227
- type: 'full' | 'partial';
228
- /** on-chain transaction hash. simulation/escrow 미배포 환경에서는 sim_xxx */
229
- txHash: string | null;
230
- }
231
- /**
232
- * Record refund 파라미터 — `status='settled'` 후 머천트가 외부 지갑에서 직접 송금하고
233
- * tx_hash를 입력해 환불을 DB-only로 기록한다. 컨트랙트 호출 없음.
214
+ * 환불은 온체인 자동 경로 — SDK 에 수동 환불 API 는 없다.
215
+ * 금액부족/잘못된토큰/만료 시 issueDepositAddress 에 지정한 refundAddress 로 자동 환불되고,
216
+ * 세션 status(expired/unresolved) + webhook 으로 통지된다.
234
217
  */
235
- interface RecordRefundParams {
236
- /** Atomic μUSDC 정수 문자열 (필수) */
237
- refund_amount: string;
238
- /** 외부 송금 transaction hash (필수, 형식 검증 안 함) */
239
- tx_hash: string;
240
- /** 환불 사유 (선택) */
241
- reason?: string;
242
- }
243
218
  /**
244
219
  * 멱등성 키 — 동일 키로 재시도 시 backend가 같은 결과 반환.
245
- * Phase 1 SDK는 사용자가 명시적으로 전달 (UUID 권장).
246
220
  */
247
221
  interface IdempotencyOptions {
248
222
  idempotencyKey?: string;
249
223
  }
250
- /**
251
- * `GET /v1/checkout/sessions/:id/refunds` 응답 row.
252
- * 필드는 backend `listSessionRefunds` 반환과 동일 — Phase 1에서는 통합 타입 미고정 (스냅샷 시점에 따라 컬럼 변동).
253
- */
254
- interface RefundEntry {
255
- id: string;
256
- session_id: string;
257
- /** 'auto' | 'record' (escrow refund vs DB-only manual) */
258
- refund_mode?: string;
259
- amount: string;
260
- /** 'pending' | 'completed' | 'failed' 등 */
261
- status?: string;
262
- tx_hash: string | null;
263
- reason?: string | null;
264
- reason_detail?: string | null;
265
- created_at: string;
266
- [key: string]: unknown;
267
- }
268
224
  interface ApiResponse<T> {
269
225
  data: T;
270
226
  error?: string;
@@ -273,6 +229,234 @@ interface ListResponse<T> {
273
229
  data: T[];
274
230
  total?: number;
275
231
  }
232
+ interface CheckoutProduct {
233
+ /** prod_... */
234
+ id: string;
235
+ name: string;
236
+ description: string | null;
237
+ image_url: string | null;
238
+ /** 'active' | 'inactive' */
239
+ status: string;
240
+ metadata: Record<string, unknown>;
241
+ mode: string;
242
+ created_at: string;
243
+ updated_at: string;
244
+ }
245
+ interface CheckoutPrice {
246
+ /** price_... */
247
+ id: string;
248
+ /** prod_... */
249
+ product_id: string;
250
+ /** 원자 단위 정수 문자열 ($1 = "1000000") — 불변 */
251
+ amount_atomic: string;
252
+ currency: string;
253
+ token_symbol: string;
254
+ /** v1: 'one_time' */
255
+ billing_type: string;
256
+ nickname: string | null;
257
+ lookup_key: string | null;
258
+ mode: string;
259
+ created_at: string;
260
+ }
261
+ interface CreateProductParams {
262
+ name: string;
263
+ description?: string;
264
+ image_url?: string;
265
+ metadata?: Record<string, unknown>;
266
+ }
267
+ interface UpdateProductParams {
268
+ name?: string;
269
+ description?: string | null;
270
+ image_url?: string | null;
271
+ metadata?: Record<string, unknown>;
272
+ status?: 'active' | 'inactive';
273
+ }
274
+ /**
275
+ * 가격 생성 입력. 금액은 둘 중 **하나** (line item 과 동일 모델):
276
+ * - `amount`(권장): 사람 표기 USD 문자열(예 "29", "0.5"). decimal 신경 쓸 필요 없음.
277
+ * - `amount_atomic`: raw μUSD 정수($1="1000000") — 고급/기존.
278
+ * 둘 다 지정하거나 둘 다 생략하면 서버가 400 을 반환한다.
279
+ */
280
+ interface CreatePriceParams {
281
+ /** 사람 표기 USD 금액(예 "29", "0.5") — 권장. amount_atomic 과 상호배타. */
282
+ amount?: string;
283
+ /** raw μUSD 정수($1="1000000") — 고급/기존. amount 와 상호배타. */
284
+ amount_atomic?: string;
285
+ currency?: string;
286
+ token_symbol?: string;
287
+ billing_type?: 'one_time';
288
+ nickname?: string;
289
+ lookup_key?: string;
290
+ }
291
+ /**
292
+ * Price는 lifecycle 없는 immutable record — 변경 가능한 것은 nickname(표시 메타)뿐.
293
+ * 금액류 필드(amount_atomic 등)는 immutable, "그만 팔기"는 Price 가 아니라 그 Price 를 쓰는
294
+ * Payment Link 를 inactive 로 한다.
295
+ */
296
+ interface UpdatePriceParams {
297
+ nickname?: string | null;
298
+ }
299
+ interface ListProductsParams {
300
+ status?: 'active' | 'inactive';
301
+ limit?: number;
302
+ offset?: number;
303
+ }
304
+ interface ListPricesParams {
305
+ limit?: number;
306
+ offset?: number;
307
+ }
308
+ interface CheckoutPaymentLink {
309
+ /** plink_... */
310
+ id: string;
311
+ /** 고엔트로피 공개 토큰 — 호스티드 URL `{checkoutBase}/plink/{share_token}` 에 사용 */
312
+ share_token: string;
313
+ /** price_... — 이 링크가 파는 가격(생성 후 고정) */
314
+ price_id: string;
315
+ title: string | null;
316
+ description: string | null;
317
+ collect_email: boolean;
318
+ email_required: boolean;
319
+ /** CAIP-2 목록 또는 null(legacy) */
320
+ allowed_pay_chains: string[] | null;
321
+ /** chain×token cell 목록 또는 null */
322
+ allowed_assets: Array<{
323
+ caip2: string;
324
+ token: string;
325
+ }> | null;
326
+ success_url: string | null;
327
+ cancel_url: string | null;
328
+ /** 'active' | 'inactive' */
329
+ status: string;
330
+ max_uses: number | null;
331
+ paid_use_count: number;
332
+ expires_at: string | null;
333
+ mode: string;
334
+ created_at: string;
335
+ updated_at: string;
336
+ }
337
+ interface CreatePaymentLinkParams {
338
+ /** price_... — bitpal.checkout.prices.create() 로 만든 가격. 필수. */
339
+ price_id: string;
340
+ title?: string;
341
+ description?: string;
342
+ /** buyer 이메일 수집(기본 true) */
343
+ collect_email?: boolean;
344
+ /** buyer 이메일 필수(기본 true). true 면 collect_email 도 true 여야 함. */
345
+ email_required?: boolean;
346
+ /** 허용 결제 체인(CAIP-2 또는 short-name). allowed_assets 가 있으면 그쪽 우선. */
347
+ allowed_pay_chains?: string[];
348
+ /** chain×token cell 허용 목록 — allowed_pay_chains 보다 우선. */
349
+ allowed_assets?: Array<{
350
+ chain: string;
351
+ token: string;
352
+ }>;
353
+ success_url?: string;
354
+ cancel_url?: string;
355
+ max_uses?: number;
356
+ /** ISO-8601 datetime */
357
+ expires_at?: string;
358
+ metadata?: Record<string, unknown>;
359
+ }
360
+ interface UpdatePaymentLinkParams {
361
+ title?: string | null;
362
+ description?: string | null;
363
+ collect_email?: boolean;
364
+ email_required?: boolean;
365
+ allowed_pay_chains?: string[] | null;
366
+ allowed_assets?: Array<{
367
+ chain: string;
368
+ token: string;
369
+ }> | null;
370
+ success_url?: string | null;
371
+ cancel_url?: string | null;
372
+ status?: 'active' | 'inactive';
373
+ max_uses?: number | null;
374
+ expires_at?: string | null;
375
+ metadata?: Record<string, unknown>;
376
+ }
377
+ interface ListPaymentLinksParams {
378
+ status?: 'active' | 'inactive';
379
+ limit?: number;
380
+ offset?: number;
381
+ }
382
+
383
+ /**
384
+ * catalog.ts — Product / immutable Price 관리 리소스 (PROD-LINK-3a-SDK)
385
+ *
386
+ * server-side SDK 전용 (secret API key). 브라우저에서 사용 금지.
387
+ *
388
+ * 사용 예:
389
+ * ```ts
390
+ * const bitpal = new BitPal({ apiKey: 'bp_test_...' });
391
+ * const { data: product } = await bitpal.checkout.products.create({ name: 'Pro Plan' });
392
+ * const { data: price } = await bitpal.checkout.prices.create(product.id, {
393
+ * amount_atomic: toAtomicUSDC('29.00'),
394
+ * });
395
+ * ```
396
+ *
397
+ * Price immutable 원칙: 가격 변경은 update가 아니라 "새 price 생성"이다.
398
+ * `prices.update`는 nickname(표시 메타)만 받는다 — 금액류 필드 변경 helper는 의도적으로 없다.
399
+ * "그만 팔기"는 Price 를 끄는 게 아니라 그 Price 를 쓰는 Payment Link 를 inactive 로 한다.
400
+ */
401
+
402
+ /** client.ts의 private request를 리소스에 주입하기 위한 시그니처 */
403
+ type CatalogRequester = <T>(method: string, path: string, body?: unknown) => Promise<T>;
404
+ declare class ProductsResource {
405
+ private readonly request;
406
+ constructor(request: CatalogRequester);
407
+ /** POST /v1/checkout/products */
408
+ create(params: CreateProductParams): Promise<ApiResponse<CheckoutProduct>>;
409
+ /** GET /v1/checkout/products */
410
+ list(params?: ListProductsParams): Promise<ListResponse<CheckoutProduct>>;
411
+ /** GET /v1/checkout/products/:id */
412
+ retrieve(productId: string): Promise<ApiResponse<CheckoutProduct>>;
413
+ /** PATCH /v1/checkout/products/:id */
414
+ update(productId: string, params: UpdateProductParams): Promise<ApiResponse<CheckoutProduct>>;
415
+ }
416
+ declare class PricesResource {
417
+ private readonly request;
418
+ constructor(request: CatalogRequester);
419
+ /** POST /v1/checkout/products/:id/prices */
420
+ create(productId: string, params: CreatePriceParams): Promise<ApiResponse<CheckoutPrice>>;
421
+ /** GET /v1/checkout/products/:id/prices */
422
+ list(productId: string, params?: ListPricesParams): Promise<ListResponse<CheckoutPrice>>;
423
+ /** GET /v1/checkout/prices/:id */
424
+ retrieve(priceId: string): Promise<ApiResponse<CheckoutPrice>>;
425
+ /**
426
+ * PATCH /v1/checkout/prices/:id — nickname(표시 메타)만.
427
+ * 금액류 필드(amount_atomic 등)는 immutable — 서버가 PRICE_IMMUTABLE_FIELD로 거부한다.
428
+ * 가격 변경은 `prices.create()`로 새 price를 만들 것. "그만 팔기"는 해당 Price 를 쓰는
429
+ * Payment Link 를 inactive 로 한다(Price 자체에는 active/inactive 개념이 없다).
430
+ */
431
+ update(priceId: string, params: UpdatePriceParams): Promise<ApiResponse<CheckoutPrice>>;
432
+ }
433
+ /**
434
+ * Payment Link 리소스 — 대시보드 없이 코드로 결제 링크 생성/관리 (PROD-LINK-4).
435
+ *
436
+ * 흐름: product 생성 → price 생성 → payment link 생성. link↔price binding 은 생성 후 고정.
437
+ *
438
+ * ```ts
439
+ * const { data: product } = await bitpal.checkout.products.create({ name: 'Pro Plan' });
440
+ * const { data: price } = await bitpal.checkout.prices.create(product.id, { amount: '29' });
441
+ * const { data: link } = await bitpal.checkout.paymentLinks.create({
442
+ * price_id: price.id,
443
+ * allowed_pay_chains: ['eip155:8453', 'solana:5eykt4Us…'],
444
+ * });
445
+ * // 호스티드 결제 페이지 URL: `{checkoutBase}/plink/${link.share_token}`
446
+ * ```
447
+ */
448
+ declare class PaymentLinksResource {
449
+ private readonly request;
450
+ constructor(request: CatalogRequester);
451
+ /** POST /v1/checkout/payment-links */
452
+ create(params: CreatePaymentLinkParams): Promise<ApiResponse<CheckoutPaymentLink>>;
453
+ /** GET /v1/checkout/payment-links */
454
+ list(params?: ListPaymentLinksParams): Promise<ListResponse<CheckoutPaymentLink>>;
455
+ /** GET /v1/checkout/payment-links/:id */
456
+ retrieve(linkId: string): Promise<ApiResponse<CheckoutPaymentLink>>;
457
+ /** PATCH /v1/checkout/payment-links/:id */
458
+ update(linkId: string, params: UpdatePaymentLinkParams): Promise<ApiResponse<CheckoutPaymentLink>>;
459
+ }
276
460
 
277
461
  /**
278
462
  * @bitpal/checkout SDK — 클라이언트
@@ -282,24 +466,40 @@ interface ListResponse<T> {
282
466
  */
283
467
 
284
468
  declare class BitPalCheckoutClient {
469
+ /** 서버 메서드용 secret 키. 공개(buyer-facing) 메서드는 없이도 동작. */
285
470
  private readonly apiKey;
286
471
  private readonly baseUrl;
287
472
  private readonly timeout;
473
+ /** PROD-LINK-3a-SDK: Product 카탈로그 관리 (server-side 전용) */
474
+ readonly products: ProductsResource;
475
+ /** PROD-LINK-3a-SDK: immutable Price 관리 — 가격 변경은 비활성화 + 새 price 생성 */
476
+ readonly prices: PricesResource;
477
+ /** PROD-LINK-4-SDK: Payment Link 관리 — 대시보드 없이 코드로 결제 링크 생성 (server-side 전용) */
478
+ readonly paymentLinks: PaymentLinksResource;
288
479
  constructor(config: BitPalConfig);
289
480
  private request;
290
481
  /**
291
482
  * 체크아웃 세션 생성.
292
483
  *
293
- * 모든 `line_items[].amount`는 atomic μUSDC 정수 문자열이어야 한다 ($1 = "1000000").
294
- * decimal 표기는 거부된다 — `toAtomicUSDC()` 헬퍼 사용 권장.
484
+ * `line_items[].amount` 는 사람 표기 USD 문자열("29", "0.5") — decimal 계산 불필요.
485
+ * 이미 raw μUSD 정수라면 `amount_atomic`("29000000") 사용(고급). 둘은 상호 배타.
295
486
  *
296
487
  * @example
297
- * import { BitPal, toAtomicUSDC } from '@bitpal/checkout';
488
+ * import { BitPal } from '@bitpal/checkout';
298
489
  * const bp = new BitPal('bp_test_...');
299
490
  * const { data } = await bp.checkout.createSession({
300
- * line_items: [{ name: 'Pro', amount: toAtomicUSDC('29.00'), currency: 'USDC' }],
491
+ * // amount: 사람 표기 USD("29", "0.5"). 금액은 USD 가격이라 체인/토큰 decimal 무관.
492
+ * line_items: [{ name: 'Pro', amount: '29', currency: 'USDC' }],
301
493
  * });
302
494
  * console.log(data.url); // → buyer를 redirect할 결제 페이지
495
+ *
496
+ * // 멀티체인 허용 — 구매자가 Base/Optimism 중 선택(하나뿐이면 자동 선택):
497
+ * // 어떤 체인·토큰이든 amount 그대로 — 서버가 발급 시 토큰 decimals 로 재스케일.
498
+ * await bp.checkout.createSession({
499
+ * line_items: [{ name: 'Pro', amount: '29', currency: 'USDC' }],
500
+ * allowed_pay_chains: ['eip155:84532', 'eip155:11155420'],
501
+ * });
502
+ * // 단일 체인 고정은 pay_chain 사용(둘은 상호 배타).
303
503
  */
304
504
  createSession(params: CreateSessionParams): Promise<ApiResponse<CheckoutSession>>;
305
505
  /** 세션 조회 */
@@ -311,109 +511,40 @@ declare class BitPalCheckoutClient {
311
511
  offset?: number;
312
512
  }): Promise<ListResponse<CheckoutSession>>;
313
513
  /**
314
- * Auto refund — escrow 보관 중일 때 컨트랙트가 buyer에게 직접 transfer.
315
- *
316
- * `params.amount` 미지정 시 backend가 잔액 전액(`type: 'full'`). 명시 시 `type: 'partial'`.
317
- * **Idempotency-Key 권장** — 같은 키로 재시도 시 backend가 같은 결과 반환.
318
- *
319
- * 머천트가 `frozen` 상태면 환불은 허용되지만, `suspended` 상태에서는 차단된다.
320
- *
321
- * @example
322
- * ```ts
323
- * import { randomUUID } from 'node:crypto';
324
- * const { data } = await bitpal.checkout.refundSession(
325
- * sessionId,
326
- * { amount: toAtomicUSDC('5.00'), reason: 'customer_requested' },
327
- * { idempotencyKey: randomUUID() },
328
- * );
329
- * console.log(data.txHash); // on-chain tx hash (또는 simulation 환경에서 sim_xxx)
330
- * ```
331
- */
332
- refundSession(sessionId: string, params?: RefundSessionParams, opts?: IdempotencyOptions): Promise<ApiResponse<RefundSessionResult>>;
333
- /**
334
- * Record refund — `status='settled'` 후 머천트가 외부 지갑에서 직접 송금하고 tx_hash를 입력.
335
- * 컨트랙트 호출 없음 (DB-only).
336
- *
337
- * **Idempotency-Key 권장**.
514
+ * 공개 세션 조회 (`GET /v1/checkout/sessions/:id/public`) — 인증 불요.
338
515
  *
339
- * @example
340
- * ```ts
341
- * await bitpal.checkout.recordRefund(
342
- * sessionId,
343
- * {
344
- * refund_amount: toAtomicUSDC('5.00'),
345
- * tx_hash: '0xabc...',
346
- * reason: 'manual_offchain_refund',
347
- * },
348
- * { idempotencyKey: randomUUID() },
349
- * );
350
- * ```
516
+ * buyer-facing 결제 페이지가 표시/자산선택에 쓰는 서버 권위 뷰. `payment_options` 로
517
+ * 구매자 선택 가능한 chain×token 을 얻고, 발급 후에는 `deposit_address` 가 채워진다.
351
518
  */
352
- recordRefund(sessionId: string, params: RecordRefundParams, opts?: IdempotencyOptions): Promise<ApiResponse<RefundEntry>>;
353
- /** 세션별 환불 내역 (auto + record 통합) */
354
- listRefunds(sessionId: string): Promise<ListResponse<RefundEntry>>;
519
+ getPublicSession(sessionId: string): Promise<ApiResponse<PublicSession>>;
355
520
  /**
356
- * CheckoutEscrow에 직접 입금한 외부 결제를 BitPal에 제출·검증.
521
+ * 주문별 비수탁 입금주소 발급 (`POST /v1/checkout/sessions/:id/deposit-address`).
357
522
  *
358
- * Buyer가 merchant UI/SDK에서 `CheckoutEscrow.deposit*()` 함수를 직접 호출한 뒤
359
- * 결과 tx_hash를 이 메서드로 제출한다. BitPal은 receipt를 fetch하여
360
- * `PaymentDeposited` 이벤트를 검증하고 세션 상태를 갱신한다.
523
+ * 안2 결제 진입점. 구매자가 자산(멀티옵션이면 chain/token)과 환불 주소를 확정하면 서버가
524
+ * 그 주문 전용 CREATE2 forwarder 주소를 돌려준다. 구매자는 아무 지갑/거래소에서 **정확한 금액**을
525
+ * 그 주소로 일반 송금하면 된다(서명·연결 불필요). watcher 가 감지 → keeper 가 정산.
361
526
  *
362
- * **인증 방식:**
363
- * - Merchant server (API key): `Authorization: Bearer bp_test_*` 헤더 자동 첨부
364
- * - Buyer 측 (session_token): `params.session_token` 전달
527
+ * refundAddress 는 입금주소에 커밋되어 발급 후 변경 불가. session_token 은 createSession 응답값.
365
528
  *
366
529
  * @example
367
530
  * ```ts
368
- * // Merchant server — API key 인증
369
- * const { data } = await bitpal.checkout.submitExternalPayment(sessionId, {
370
- * tx_hash: '0xabc...',
371
- * chain: 'base',
531
+ * const { data } = await bitpal.checkout.issueDepositAddress(sessionId, {
532
+ * session_token: session.session_token!,
533
+ * refundAddress: '0xBuyerWallet...',
534
+ * chain: 'eip155:8453', // 멀티옵션 세션만 필요
535
+ * token: 'USDC',
372
536
  * });
373
- * console.log(data.validation_status); // 'valid' | 'underpaid' | 'overpaid' | ...
374
- * console.log(data.session_status); // 'paid' | 'unresolved_underpaid' | ...
537
+ * console.log(data.depositAddress, data.expectedAmount); // 이 주소로 정확 금액 송금
375
538
  * ```
376
539
  */
377
- submitExternalPayment(sessionId: string, params: SubmitExternalPaymentParams, opts?: IdempotencyOptions): Promise<ApiResponse<SubmitExternalPaymentResult>>;
540
+ issueDepositAddress(sessionId: string, params: IssueDepositAddressParams): Promise<ApiResponse<DepositAddress>>;
378
541
  /**
379
- * Gasless checkout payment through the BitPal API relayer.
542
+ * 경량 상태 폴링 (`GET /v1/checkout/sessions/:id/status`) — 인증 불요.
380
543
  *
381
- * The buyer signs **two** EIP-712 typed-data structures and the API calls
382
- * `CheckoutEscrow.depositWithAuthorization()` with the platform relayer:
383
- *
384
- * 1. **EIP-3009 USDC TransferWithAuthorization** (`params.authorization`) —
385
- * authorizes USDC transfer from buyer to escrow.
386
- * 2. **PaymentAuthorization** (`params.payment_auth`, since SDK v0.2.0) —
387
- * binds the entire payment intent (paymentId, merchant, amount, fee,
388
- * reserve, duration) to the buyer's signature. Without this, a compromised
389
- * gateway key could redirect funds to an attacker-controlled merchant.
390
- *
391
- * Build the PaymentAuthorization typed-data with `buildPaymentAuthTypedData()`.
392
- * The PaymentAuthorization nonce comes from `CheckoutEscrow.paymentAuthNonce(payer)`.
393
- *
394
- * Use the returned session/order state only as immediate UX feedback; the
395
- * merchant backend should finalize fulfillment from signed webhooks.
396
- *
397
- * @breaking-change v0.2.0 — `payment_auth` field is now required. v0.1.x clients
398
- * must upgrade their signing flow. See MIGRATION_v0.2.md.
399
- */
400
- payWithAuthorization(sessionId: string, params: PayWithAuthorizationParams, opts?: IdempotencyOptions): Promise<ApiResponse<CheckoutPaymentResult>>;
401
- /**
402
- * 세션의 external on-chain 결제 검증 기록 목록 조회.
403
- *
404
- * `getSession()`의 `payment_observations` 필드와 동일한 데이터를 반환하지만
405
- * 검증 기록만 명시적으로 조회할 때 사용한다.
406
- *
407
- * @example
408
- * ```ts
409
- * const { data } = await bitpal.checkout.getExternalPaymentStatus(sessionId);
410
- * const latest = data[0];
411
- * if (latest?.finality_status === 'final_confirmed') {
412
- * // 12 confirmations 완료 — 결제 확정
413
- * }
414
- * ```
544
+ * status: awaiting_deposit → deposit_detected → paid_confirmed/swept. 확정/정산은 webhook 으로도
545
+ * 통지되므로, 서버 사이드 확정은 webhook 을 신뢰(폴링은 buyer UX 용).
415
546
  */
416
- getExternalPaymentStatus(sessionId: string): Promise<ApiResponse<PaymentObservation[]>>;
547
+ getStatus(sessionId: string): Promise<ApiResponse<SessionStatus>>;
417
548
  /** 수수료 미리보기 — `/v1/checkout/fee-preview` (Phase 1 credit system 폐기 후 canonical path) */
418
549
  previewFee(amount: string): Promise<ApiResponse<FeePreview>>;
419
550
  }
@@ -425,18 +556,12 @@ declare class BitPalError extends Error {
425
556
  /**
426
557
  * @bitpal/checkout — Webhook 서명 검증 + 이벤트 타입
427
558
  *
428
- * BitPal backend의 canonical webhook contract와 1:1 정합:
429
- * apps/api/src/services/webhook-canonical-delivery.ts
430
- * apps/api/src/__tests__/webhook-canonical-delivery.test.ts
431
- *
432
- * 이벤트 명/서명 형식이 backend와 drift하면 머천트 검증이 깨진다.
559
+ * BitPal 이 보내는 canonical webhook contract(envelope/서명/헤더)와 1:1 정합한다.
433
560
  */
434
561
  /**
435
- * 발송되는 webhook 이벤트 타입.
436
- * Backend `services/checkout-webhook.ts:CHECKOUT_WEBHOOK_EVENTS`와 동일 — drift 시
437
- * 머천트 코드의 분기 매칭이 실패한다.
562
+ * BitPal 이 발송하는 webhook 이벤트 타입 전체 목록.
438
563
  */
439
- declare const CHECKOUT_WEBHOOK_EVENTS: readonly ["checkout.session.created", "checkout.session.paid", "checkout.session.settled", "checkout.session.expired", "checkout.session.unresolved", "checkout.session.release_deferred", "checkout.payment.failed", "checkout.payment.finalized", "checkout.payment.revoked", "checkout.refund.recorded", "checkout.refund.completed", "checkout.refund.partial"];
564
+ declare const CHECKOUT_WEBHOOK_EVENTS: readonly ["checkout.session.created", "checkout.session.deposit_detected", "checkout.session.paid", "checkout.session.settled", "checkout.session.expired", "checkout.session.unresolved", "checkout.refund.recorded"];
440
565
  type CheckoutWebhookEvent = (typeof CHECKOUT_WEBHOOK_EVENTS)[number];
441
566
  /**
442
567
  * Canonical envelope (HTTP body).
@@ -482,16 +607,29 @@ declare const WEBHOOK_HEADERS: {
482
607
  * import { verifyWebhookSignature, parseWebhookEvent, WEBHOOK_HEADERS } from '@bitpal/checkout';
483
608
  *
484
609
  * app.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
485
- * const sig = req.header(WEBHOOK_HEADERS.signature) ?? '';
486
- * const ok = await verifyWebhookSignature(req.body.toString(), sig, process.env.BITPAL_WEBHOOK_SECRET!);
610
+ * const raw = req.body.toString('utf8'); // raw body — parse/re-serialize 하면 서명 깨짐
611
+ * const ok = await verifyWebhookSignature(
612
+ * raw,
613
+ * req.header(WEBHOOK_HEADERS.signature) ?? '',
614
+ * process.env.BITPAL_WEBHOOK_SECRET!,
615
+ * { timestamp: req.header(WEBHOOK_HEADERS.timestamp) ?? '' }, // replay 방어 — 필수
616
+ * );
487
617
  * if (!ok) return res.status(400).send('invalid signature');
488
- * const event = parseWebhookEvent(req.body.toString());
618
+ * const event = parseWebhookEvent(raw);
619
+ * // dedup 은 서명된 body 의 event.id 로 (헤더 X-Webhook-Id 는 미서명)
620
+ * if (await alreadyProcessed(event.id)) return res.status(200).send('dup');
489
621
  * if (event.event === 'checkout.session.paid') { ... }
490
622
  * res.status(200).send('ok');
491
623
  * });
492
624
  * ```
493
625
  */
494
- declare function verifyWebhookSignature(payload: string, signature: string, secret: string): Promise<boolean>;
626
+ interface VerifyWebhookOptions {
627
+ /** `X-Webhook-Timestamp` 헤더 값(ISO UTC). 서명 대상에 포함되며 freshness 검사에 쓰인다. 필수. */
628
+ timestamp: string;
629
+ /** freshness 허용 오차(초). 기본 300(5분). |now - timestamp| 초과 시 replay 로 간주해 거부. */
630
+ toleranceSec?: number;
631
+ }
632
+ declare function verifyWebhookSignature(payload: string, signature: string, secret: string, opts?: VerifyWebhookOptions): Promise<boolean>;
495
633
  /**
496
634
  * Webhook envelope 파싱.
497
635
  * 형식 검증 후 `WebhookPayload` 타입으로 캐스팅.
@@ -501,185 +639,43 @@ declare function verifyWebhookSignature(payload: string, signature: string, secr
501
639
  declare function parseWebhookEvent(body: string): WebhookPayload;
502
640
 
503
641
  /**
504
- * amount.ts — atomic μUSDC 변환 헬퍼
642
+ * amount.ts — atomic ↔ decimal 변환 헬퍼 (임의 decimals + USDC 하위호환)
505
643
  *
506
- * BitPal API는 모든 amount를 atomic 정수 문자열로 받는다 (USDC/USDT 6 decimals).
507
- * $1 → "1000000"
508
- * $10 → "10000000"
509
- * $0.5 → "500000"
644
+ * BitPal API는 모든 amount를 atomic 정수 문자열로 받는다. decimals 는 토큰마다 다르다:
645
+ * USDC/USDT(Base/Arb/Tron/Solana) = 6, BSC-USD(BNB USDT) = 18. → payment_options[].decimals /
646
+ * PublicSession.token_decimals 로 서버가 내려준다. 6dp 를 하드코딩하면 non-6dp 토큰에서 금액이 틀린다.
510
647
  *
511
648
  * 정밀도 손실 방지를 위해 BigInt 연산만 사용한다 (Number 변환 금지 — CLAUDE.md 정책).
649
+ * $1(6dp) → "1000000" $1(18dp) → "1000000000000000000"
512
650
  */
513
651
  /**
514
- * decimal 문자열 → atomic μUSDC 문자열
515
- *
516
- * @example
517
- * toAtomicUSDC('29.00') // → '29000000'
518
- * toAtomicUSDC('0.5') // → '500000'
519
- * toAtomicUSDC('1000') // → '1000000000'
652
+ * decimal 문자열 → atomic 문자열 (임의 decimals).
520
653
  *
521
- * @throws {Error} 음수, 6자리 초과 소수, 형식 오류
654
+ * @param decimal 소수 문자열(음수 불가, 소수 자리 ≤ decimals)
655
+ * @param decimals 토큰 decimals (예: 6, 18). payment_options[].decimals 사용.
656
+ * @throws {Error} 음수, decimals 초과 소수 자리, 형식 오류
657
+ * @example toAtomic('29.00', 6) // '29000000' toAtomic('1.5', 18) // '1500000000000000000'
522
658
  */
523
- declare function toAtomicUSDC(decimal: string): string;
659
+ declare function toAtomic(decimal: string, decimals: number): string;
524
660
  /**
525
- * atomic μUSDC 문자열 → 사람이 읽기 좋은 decimal 문자열
526
- *
527
- * @example
528
- * fromAtomicUSDC('29000000') // → '29.00'
529
- * fromAtomicUSDC('500000') // → '0.50'
530
- * fromAtomicUSDC('1500000') // → '1.50'
661
+ * atomic 문자열 → 사람이 읽기 좋은 decimal 문자열 (임의 decimals).
662
+ * 최소 2자리 소수를 유지하되(예: '29.00'), decimals 만큼만 노출.
531
663
  *
532
664
  * @throws {Error} 정수 문자열이 아니면
665
+ * @example fromAtomic('29000000', 6) // '29.00' fromAtomic('1500000000000000000', 18) // '1.50'
533
666
  */
534
- declare function fromAtomicUSDC(atomic: string): string;
535
-
667
+ declare function fromAtomic(atomic: string, decimals: number): string;
536
668
  /**
537
- * typed-data.ts — Q5 C-01 옵션 2 (SDK v0.2.0).
538
- *
539
- * BitPal Checkout 의 EIP-712 typed-data helper. SDK 가 모든 typed-data 작업을 직접
540
- * 수행하지 않고 (서명은 머천트의 wallet provider 가) **typed-data 객체만 생성** 한다.
541
- *
542
- * 사용 예 (viem):
543
- *
544
- * ```ts
545
- * import { buildPaymentAuthTypedData } from '@bitpal/checkout';
546
- * import { signTypedData } from 'viem/accounts';
547
- *
548
- * const td = buildPaymentAuthTypedData({
549
- * escrowAddress: '0x...',
550
- * chainId: 8453,
551
- * paymentId: '0x...', // = toBytes32(sessionId)
552
- * payer: buyer.address,
553
- * merchant: session.seller_wallet,
554
- * token: session.token_address,
555
- * amount: session.amount_total,
556
- * feeAmount: '0',
557
- * reserveAmount: '0',
558
- * duration: '0',
559
- * deadline: String(Math.floor(Date.now()/1000) + 3600),
560
- * nonce: String(await escrow.read.paymentAuthNonce(buyer.address)),
561
- * });
562
- * const sig = await walletClient.signTypedData(td);
563
- * ```
564
- *
565
- * 사용 예 (wagmi `useSignTypedData`):
566
- *
567
- * ```tsx
568
- * const { signTypedDataAsync } = useSignTypedData();
569
- * const td = buildPaymentAuthTypedData({ ... });
570
- * const sig = await signTypedDataAsync(td);
571
- * ```
572
- */
573
-
574
- /**
575
- * Build EIP-712 typed-data object for PaymentAuthorization signing.
576
- * Returns a viem-compatible structure (also compatible with wagmi/ethers v6 signTypedData).
669
+ * decimal → atomic μUSDC (6dp). 하위호환 별칭 — 새 코드는 `toAtomic(decimal, decimals)` 권장
670
+ * (BNB USDT=18dp 등 non-6dp 토큰은 이 헬퍼로 처리 불가).
671
+ * @example toAtomicUSDC('29.00') // '29000000'
577
672
  */
578
- declare function buildPaymentAuthTypedData(args: PaymentAuthTypedDataArgs): {
579
- readonly domain: {
580
- readonly name: "CheckoutEscrow";
581
- readonly version: "1";
582
- readonly chainId: number;
583
- readonly verifyingContract: `0x${string}`;
584
- };
585
- readonly types: {
586
- readonly PaymentAuthorization: readonly [{
587
- readonly name: "paymentId";
588
- readonly type: "bytes32";
589
- }, {
590
- readonly name: "payer";
591
- readonly type: "address";
592
- }, {
593
- readonly name: "merchant";
594
- readonly type: "address";
595
- }, {
596
- readonly name: "token";
597
- readonly type: "address";
598
- }, {
599
- readonly name: "amount";
600
- readonly type: "uint256";
601
- }, {
602
- readonly name: "feeAmount";
603
- readonly type: "uint256";
604
- }, {
605
- readonly name: "reserveAmount";
606
- readonly type: "uint256";
607
- }, {
608
- readonly name: "duration";
609
- readonly type: "uint256";
610
- }, {
611
- readonly name: "deadline";
612
- readonly type: "uint256";
613
- }, {
614
- readonly name: "nonce";
615
- readonly type: "uint256";
616
- }];
617
- };
618
- readonly primaryType: "PaymentAuthorization";
619
- readonly message: {
620
- readonly paymentId: `0x${string}`;
621
- readonly payer: `0x${string}`;
622
- readonly merchant: `0x${string}`;
623
- readonly token: `0x${string}`;
624
- readonly amount: bigint;
625
- readonly feeAmount: bigint;
626
- readonly reserveAmount: bigint;
627
- readonly duration: bigint;
628
- readonly deadline: bigint;
629
- readonly nonce: bigint;
630
- };
631
- };
632
- /**
633
- * Args for the EIP-712 ConfirmReceipt typed-data.
634
- * Used when buyer signs an off-chain receipt confirmation that BitPal gateway relays
635
- * on-chain via `confirmReceiptWithSignature` (Q4 H-01).
636
- */
637
- interface ConfirmReceiptTypedDataArgs {
638
- escrowAddress: string;
639
- chainId: number;
640
- paymentId: string;
641
- payer: string;
642
- deadline: string;
643
- nonce: string;
644
- }
645
- /**
646
- * Build EIP-712 typed-data object for ConfirmReceipt signing (Q4 H-01).
647
- */
648
- declare function buildConfirmReceiptTypedData(args: ConfirmReceiptTypedDataArgs): {
649
- readonly domain: {
650
- readonly name: "CheckoutEscrow";
651
- readonly version: "1";
652
- readonly chainId: number;
653
- readonly verifyingContract: `0x${string}`;
654
- };
655
- readonly types: {
656
- readonly ConfirmReceipt: readonly [{
657
- readonly name: "paymentId";
658
- readonly type: "bytes32";
659
- }, {
660
- readonly name: "payer";
661
- readonly type: "address";
662
- }, {
663
- readonly name: "deadline";
664
- readonly type: "uint256";
665
- }, {
666
- readonly name: "nonce";
667
- readonly type: "uint256";
668
- }];
669
- };
670
- readonly primaryType: "ConfirmReceipt";
671
- readonly message: {
672
- readonly paymentId: `0x${string}`;
673
- readonly payer: `0x${string}`;
674
- readonly deadline: bigint;
675
- readonly nonce: bigint;
676
- };
677
- };
673
+ declare function toAtomicUSDC(decimal: string): string;
678
674
  /**
679
- * Convert a session ID string into a 32-byte hex (`paymentId`) suitable for typed-data signing.
680
- * Mirrors the backend `toBytes32(sessionId)` helper.
675
+ * atomic μUSDC(6dp) → decimal. 하위호환 별칭 — 새 코드는 `fromAtomic(atomic, decimals)` 권장.
676
+ * @example fromAtomicUSDC('29000000') // '29.00'
681
677
  */
682
- declare function sessionIdToPaymentId(sessionId: string): `0x${string}`;
678
+ declare function fromAtomicUSDC(atomic: string): string;
683
679
 
684
680
  /**
685
681
  * @bitpal/checkout — BitPal Checkout SDK
@@ -693,10 +689,11 @@ declare function sessionIdToPaymentId(sessionId: string): `0x${string}`;
693
689
  * const bitpal = new BitPal({ apiKey: 'bp_test_...' });
694
690
  *
695
691
  * const { data: session } = await bitpal.checkout.createSession({
696
- * line_items: [{ name: 'Pro Plan', amount: '29.00', currency: 'USDC' }],
692
+ * // amount: 사람 표기 USD("29","0.5"). decimal 계산 불필요 — 체인/토큰 decimal 무관.
693
+ * line_items: [{ name: 'Pro Plan', amount: '29', currency: 'USDC' }],
697
694
  * });
698
695
  *
699
- * console.log(session.url); // 호스티드 결제 페이지 URL
696
+ * console.log(session.url); // 호스티드 결제 페이지 URL (checkout_url 별칭)
700
697
  * ```
701
698
  */
702
699
 
@@ -708,4 +705,4 @@ declare class BitPal {
708
705
  constructor(config: BitPalConfig | string);
709
706
  }
710
707
 
711
- export { type ApiResponse, BitPal, BitPalCheckoutClient, type BitPalConfig, BitPalError, CHECKOUT_WEBHOOK_EVENTS, type CheckoutPaymentResult, type CheckoutSession, type CheckoutWebhookEvent, type ConfirmReceiptTypedDataArgs, type CreateSessionParams, type ExternalPaymentConfig, type FeePreview, type IdempotencyOptions, type LineItem, type ListResponse, type PayWithAuthorizationParams, type PaymentAuthTypedDataArgs, type PaymentObservation, type RecordRefundParams, type RefundEntry, type RefundSessionParams, type RefundSessionResult, type SubmitExternalPaymentParams, type SubmitExternalPaymentResult, WEBHOOK_HEADERS, type WebhookPayload, buildConfirmReceiptTypedData, buildPaymentAuthTypedData, fromAtomicUSDC, parseWebhookEvent, sessionIdToPaymentId, toAtomicUSDC, verifyWebhookSignature };
708
+ export { type ApiResponse, BitPal, BitPalCheckoutClient, type BitPalConfig, BitPalError, CHECKOUT_WEBHOOK_EVENTS, type CheckoutLineItemInput, type CheckoutPaymentLink, type CheckoutPrice, type CheckoutProduct, type CheckoutSession, type CheckoutWebhookEvent, type CreatePaymentLinkParams, type CreatePriceParams, type CreateProductParams, type CreateSessionParams, type DepositAddress, type FeePreview, type IdempotencyOptions, type IssueDepositAddressParams, type LineItem, type ListPaymentLinksParams, type ListPricesParams, type ListProductsParams, type ListResponse, PaymentLinksResource, type PaymentOption, type PriceLineItem, PricesResource, ProductsResource, type PublicSession, type SessionStatus, type UpdatePaymentLinkParams, type UpdatePriceParams, type UpdateProductParams, WEBHOOK_HEADERS, type WebhookPayload, fromAtomic, fromAtomicUSDC, parseWebhookEvent, toAtomic, toAtomicUSDC, verifyWebhookSignature };