@nexus-cross/pop 1.4.0-beta.1 → 1.4.0-beta.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.
@@ -1,6 +1,6 @@
1
1
  /** 0x-prefixed 주소. viem Address에 의존하지 않는 도메인 표현. */
2
2
  type Address = string;
3
- /** 0x-prefixed hex 문자열 (서명/salt/digest/해시 등). */
3
+ /** 0x-prefixed hex 문자열 (서명/digest/drop key/해시 등). */
4
4
  type Hex = string;
5
5
  /** 소셜 식별자 string (컨트랙트 `id`). 예: 'theo_13303'. */
6
6
  type Id = string;
@@ -28,7 +28,7 @@ interface DepositParams {
28
28
  token: Address;
29
29
  /** raw 토큰 수량 (wei-scale). BigInt 유지. */
30
30
  amount: bigint;
31
- /** 비밀 문구. 미지정 시 CryptoPort.randomSecret()로 생성. (expiry는 계약이 결정.) */
31
+ /** 비밀 문구. 미지정 시 CryptoPort.randomSecret()로 생성. */
32
32
  secret?: Secret;
33
33
  /**
34
34
  * 수령인에게 보여줄 메시지 (최대 140 runes). 컨트랙트에는 필드가 없고
@@ -38,7 +38,8 @@ interface DepositParams {
38
38
  /** 카드 디자인 id. 목록은 `listEnvelopes()` (GET /envelopes). */
39
39
  envelopeId?: string;
40
40
  }
41
- interface DepositResult {
41
+ interface UnmappedDepositResult {
42
+ readonly isMapped: false;
42
43
  /** 컨트랙트에 커밋된 임시 claim 지갑 주소 = 이 드롭의 키. */
43
44
  readonly claimAddress: Address;
44
45
  readonly secretHash: SecretHash;
@@ -46,7 +47,14 @@ interface DepositResult {
46
47
  readonly withdrawLink: string;
47
48
  readonly depositTxHash: Hex;
48
49
  }
50
+ interface MappedDepositResult {
51
+ readonly isMapped: true;
52
+ readonly depositTxHash: Hex;
53
+ }
54
+ type DepositResult = UnmappedDepositResult | MappedDepositResult;
49
55
  interface WithdrawParams {
56
+ /** 링크의 sender query 값 = 온체인 sponsor. */
57
+ sponsor: Address;
50
58
  /** 수령 주소 — 수령인 본인이 지정. 서명에 바인딩된다. */
51
59
  recipient: Address;
52
60
  /** X OAuth 검증 후 백엔드에서 받은 임시 claim 지갑 주소. drops() 조회 키. */
@@ -60,7 +68,9 @@ interface WithdrawResult {
60
68
  readonly txHash: Hex;
61
69
  }
62
70
  interface RefundParams {
63
- /** 환불할 드롭의 claimAddr. 만료 후 sponsor(msg.sender)만 호출 가능. */
71
+ /** 드롭 sponsor. */
72
+ sponsor: Address;
73
+ /** 환불할 드롭의 claimAddr. sponsor(msg.sender)만 호출 가능. */
64
74
  claimAddress: Address;
65
75
  }
66
76
  interface RefundResult {
@@ -71,6 +81,14 @@ interface BatchClaimParams {
71
81
  id: Id;
72
82
  /** 핸들 소유 증명용 X OAuth 토큰. 서명 발급의 전제. */
73
83
  oauth: OAuthProof;
84
+ /** anchor drop의 sponsor(링크 sender). */
85
+ sponsor: Address;
86
+ /** 첫 unmapped 드롭의 임시 claim 지갑 주소. */
87
+ claimAddress: Address;
88
+ /** 첫 드롭 링크 fragment의 secret. */
89
+ secret: Secret;
90
+ /** 첫 드롭의 임시 claim 개인키. */
91
+ claimKey: Hex;
74
92
  /**
75
93
  * 기대하는 수령 주소. 서명은 **SIWE 인증 주소**에 바인딩되므로, 다르면
76
94
  * `SIGN_FAILED`로 끊는다(다른 주소로 받으려면 그 주소로 SIWE 로그인).
@@ -81,11 +99,11 @@ interface BatchClaimParams {
81
99
  deadline?: bigint;
82
100
  /** deadline 자동 계산용 TTL(초). 기본 1800. */
83
101
  deadlineTtlSeconds?: bigint;
84
- /** tx 1건이 처리할 드롭 수(서명 대상 아님 — 페이지 크기). 기본 30. */
102
+ /** tx 한 건에 포함할 drop key 수. 기본 30. 호출마다 새 validator 서명을 받는다. */
85
103
  maxCount?: number;
86
104
  }
87
105
  interface BatchClaimResult {
88
- /** 페이지별 tx hash. 드롭이 maxCount 이하면 1건. */
106
+ /** 현재 batch 호출의 tx hash(호환을 위해 배열 유지). */
89
107
  readonly txHashes: readonly Hex[];
90
108
  /** 실제로 서명에 바인딩된 수령 주소. */
91
109
  readonly recipient: Address;
@@ -93,7 +111,7 @@ interface BatchClaimResult {
93
111
  readonly nonce: bigint;
94
112
  readonly deadline: bigint;
95
113
  }
96
- type SafeDropErrorCode = 'MISSING_SENDER' | 'MISSING_RECIPIENT' | 'MISSING_SECRET' | 'MISSING_CLAIM_KEY' | 'MISSING_CLAIM_ADDRESS' | 'INVALID_AMOUNT' | 'INVALID_TOKEN' | 'DROP_NOT_FOUND' | 'SECRET_MISMATCH' | 'SIGN_FAILED' | 'CHAIN_ERROR' | 'API_ERROR' | 'INVALID_PARAM' | 'RATE_LIMITED' | 'INVALID_OAUTH_TOKEN' | 'UNAUTHORIZED' | 'WALLET_NOT_FOUND' | 'SEND_BLOCKED' | 'ENVELOPE_NOT_FOUND' | 'PENDING_LIMIT_EXCEEDED' | 'X_CONNECTION_NOT_FOUND';
114
+ type SafeDropErrorCode = 'MISSING_SENDER' | 'MISSING_RECIPIENT' | 'MISSING_SECRET' | 'MISSING_CLAIM_KEY' | 'MISSING_CLAIM_ADDRESS' | 'INVALID_AMOUNT' | 'INVALID_TOKEN' | 'DROP_NOT_FOUND' | 'SECRET_MISMATCH' | 'SIGN_FAILED' | 'CHAIN_ERROR' | 'API_ERROR' | 'INVALID_PARAM' | 'RATE_LIMITED' | 'INVALID_OAUTH_TOKEN' | 'UNAUTHORIZED' | 'WALLET_NOT_FOUND' | 'SEND_BLOCKED' | 'ENVELOPE_NOT_FOUND' | 'PENDING_LIMIT_EXCEEDED' | 'IDENTIFIER_NOT_MAPPED' | 'X_CONNECTION_NOT_FOUND';
97
115
  declare class SafeDropError extends Error {
98
116
  readonly code: SafeDropErrorCode;
99
117
  readonly details?: Record<string, unknown>;
@@ -108,6 +126,9 @@ interface XConnection {
108
126
  readonly profileImageUrl: string;
109
127
  /** SIWE 인증 주소. 본문으로 고를 수 없다. */
110
128
  readonly walletAddress: Address;
129
+ readonly revealYou: boolean;
130
+ readonly onchainMapped: boolean;
131
+ readonly mappedRecipient: Address | null;
111
132
  }
112
133
  /** 드롭을 보낸 sponsor. X 연결이 없으면 handle/displayName/profileImageUrl은 빈 문자열. */
113
134
  interface DropSender {
@@ -118,6 +139,10 @@ interface DropSender {
118
139
  }
119
140
  /** GET /drops의 개별 항목. claimAddress로 개별 수령(withdraw)을 진행한다. */
120
141
  interface PendingDrop {
142
+ /** 백엔드 drop id. feedback 등록에 사용한다. */
143
+ readonly id: number;
144
+ /** 현재 컨트랙트의 bytes32 drop key. */
145
+ readonly dropKey: Hex;
121
146
  readonly claimAddress: Address;
122
147
  readonly token: Address;
123
148
  /** raw 토큰 수량 (wei-scale). */
@@ -138,6 +163,8 @@ interface DropInbox {
138
163
  readonly totalAmount: bigint;
139
164
  /** 첫 수령은 개별 claim만 허용 — 일괄 수령 CTA 게이트. */
140
165
  readonly hasClaimedBefore: boolean;
166
+ readonly mappedRecipient: Address | null;
167
+ readonly pendingChangeTo: Address | null;
141
168
  }
142
169
  /** GET /envelopes — 카드 디자인. 공개 엔드포인트. */
143
170
  interface Envelope {
@@ -147,30 +174,50 @@ interface Envelope {
147
174
  readonly badge: string;
148
175
  readonly sortOrder: number;
149
176
  }
150
- /** GET /leaderboards — identifier별 pending 잔액 상위(최대 10). 공개 엔드포인트. */
177
+ /** GET /leaderboards — identifier별 pending 잔액. */
151
178
  interface LeaderboardEntry {
152
179
  readonly identifier: string;
153
180
  /** 수령 가능(pending) 합계 (wei-scale). */
154
181
  readonly balance: bigint;
155
182
  /** 최근 Deposited 금액 (wei-scale). */
156
183
  readonly lastDepositAmount: bigint;
184
+ readonly rank: number;
185
+ readonly previousRank: number | null;
186
+ readonly profileImageUrl: string;
187
+ }
188
+ interface LeaderboardPage {
189
+ readonly items: readonly LeaderboardEntry[];
190
+ readonly page: number;
191
+ readonly pageSize: number;
192
+ readonly total: number;
193
+ }
194
+ interface MyLeaderboardEntry extends Omit<LeaderboardEntry, 'rank'> {
195
+ readonly rank: number | null;
196
+ }
197
+ type HistoryType = 'sent' | 'received';
198
+ interface HistoryParty {
199
+ readonly address: Address;
200
+ readonly handle: string;
201
+ readonly displayName: string;
202
+ readonly profileImageUrl: string;
157
203
  }
158
- type PopEventName = 'Deposited' | 'Withdrawn' | 'Refunded' | 'BatchWithdrawn';
159
- /** GET /histories 항목. 이벤트가 담지 않는 주소는 null. */
204
+ /** GET /histories의 drop 중심 항목. */
160
205
  interface HistoryEntry {
161
- readonly eventName: PopEventName | (string & {});
162
- readonly txHash: Hex;
163
- readonly blockNumber: number;
164
- readonly logIndex: number;
165
- readonly contractAddress: Address;
166
- readonly fromAddress: Address | null;
167
- readonly toAddress: Address | null;
168
- readonly tempTo: Address | null;
169
- readonly identifier: string;
170
- /** wei-scale. */
206
+ readonly id: number;
207
+ readonly type: HistoryType;
208
+ readonly status: string;
209
+ readonly token: Address;
171
210
  readonly amount: bigint;
172
- readonly createdAt: string;
173
- readonly payload?: Record<string, unknown>;
211
+ readonly claimAddress: Address;
212
+ readonly depositTxHash: Hex;
213
+ readonly depositedAt: string;
214
+ readonly resolvedTxHash: Hex | null;
215
+ readonly resolvedAt: string | null;
216
+ readonly message: string;
217
+ readonly feedback: string | null;
218
+ readonly envelopeId: string;
219
+ readonly sender: HistoryParty;
220
+ readonly receiver: HistoryParty;
174
221
  }
175
222
  interface HistoryPage {
176
223
  readonly items: readonly HistoryEntry[];
@@ -182,8 +229,7 @@ interface HistoryPage {
182
229
  /**
183
230
  * POST /batch-claim-signature 결과 — EIP-712 ValidatorClaim 서명.
184
231
  * recipient는 항상 Bearer 토큰의 SIWE 주소다(본문으로 못 고른다).
185
- * 같은 id의 live 드롭이 모두 빠질 때까지 페이지네이션된 온체인 호출에
186
- * **재사용**한다 — 페이지마다 다시 발급받지 않는다.
232
+ * 서명은 성공한 온체인 호출 1건마다 nonce와 함께 소비된다.
187
233
  */
188
234
  interface BatchClaimSignature {
189
235
  readonly id: Id;
@@ -192,6 +238,15 @@ interface BatchClaimSignature {
192
238
  readonly deadline: bigint;
193
239
  readonly signature: Hex;
194
240
  }
241
+ interface RecipientSignature {
242
+ readonly id: Id;
243
+ readonly nonce: bigint;
244
+ readonly deadline: bigint;
245
+ readonly signature: Hex;
246
+ }
247
+ interface RecipientChangeSignature extends RecipientSignature {
248
+ readonly newRecipient: Address;
249
+ }
195
250
 
196
251
  /**
197
252
  * 순수 계산이 아니라 외부 구현(해시 라이브러리/CSPRNG)이 필요한 암호 연산.
@@ -229,10 +284,6 @@ interface SafeDropApiPort {
229
284
  createClaimWallet(params: {
230
285
  sender: Address;
231
286
  recipient: SocialIdentifier;
232
- /** 수령인에게 보여줄 메시지 (≤140 runes, 백엔드 저장 전용). */
233
- message?: string;
234
- /** 카드 디자인 id (GET /envelopes). */
235
- envelopeId?: string;
236
287
  }): Promise<{
237
288
  claimAddress: Address;
238
289
  id: Id;
@@ -246,13 +297,8 @@ interface SafeDropApiPort {
246
297
  }): Promise<void>;
247
298
  /**
248
299
  * Withdraw: X OAuth 검증 후 복호화된 임시 claim 개인키 반환 (point of return).
249
- * dropId가 아니라 (sender_address + OAuth 토큰 소유자의 identifier) 조합으로
250
- * 해당하는 최신 pending 지갑 키를 찾는다 — one-pop-api /wallets/private-key.
251
- *
252
- * ⚠️ 한 (sender, identifier)에 pending 드롭이 여러 개 있을 수 있다(백엔드가
253
- * 중복 제한을 풀었다). 이 엔드포인트는 그중 **최신 1건**만 돌려주고 특정
254
- * claimAddress를 고르는 파라미터가 없다 — 같은 sender가 보낸 여러 드롭은
255
- * 링크마다 순차로 수령해야 한다. 전체 목록은 `listDrops()`로 본다.
300
+ * claimAddress로 특정 pending 지갑을 선택하고 OAuth 토큰으로 handle 소유권을
301
+ * 증명한다 — one-pop-api /wallets/private-key.
256
302
  */
257
303
  retrieveClaimKey(params: {
258
304
  claimAddress: Address;
@@ -273,13 +319,20 @@ interface SafeDropApiPort {
273
319
  listEnvelopes?(params?: {
274
320
  locale?: string;
275
321
  }): Promise<readonly Envelope[]>;
276
- /** GET /leaderboards — 토큰별 pending 잔액 상위. 공개(인증 불필요). */
322
+ /** GET /leaderboards — 토큰별 pending 잔액. 공개(인증 불필요). */
277
323
  getLeaderboard?(params: {
278
324
  token: Address;
279
- }): Promise<readonly LeaderboardEntry[]>;
325
+ page?: number;
326
+ pageSize?: number;
327
+ identifier?: string;
328
+ }): Promise<LeaderboardPage>;
329
+ getMyLeaderboardEntry?(params: {
330
+ token: Address;
331
+ }): Promise<MyLeaderboardEntry>;
280
332
  /** GET /histories — 내가 sender이거나 최종 수령인인 온체인 이벤트. Bearer JWT. */
281
- listHistories?(params?: {
282
- event?: PopEventName;
333
+ listHistories?(params: {
334
+ type: HistoryType;
335
+ token?: Address;
283
336
  /** 1-based (기본 1). */
284
337
  page?: number;
285
338
  /** 기본 20, 최대 100. */
@@ -293,6 +346,25 @@ interface SafeDropApiPort {
293
346
  }): Promise<XConnection>;
294
347
  /** DELETE /x-connections — 연결 해제. 이미 없으면 조용히 성공(idempotent). */
295
348
  disconnectX?(): Promise<void>;
349
+ submitFeedback?(params: {
350
+ dropId: number;
351
+ message: string;
352
+ }): Promise<string>;
353
+ setRevealYou?(params: {
354
+ revealYou: boolean;
355
+ }): Promise<boolean>;
356
+ requestRecipientChangeSignature?(params: {
357
+ id: Id;
358
+ oauth: OAuthProof;
359
+ nonce: bigint;
360
+ deadline: bigint;
361
+ }): Promise<RecipientChangeSignature>;
362
+ requestRecipientResetSignature?(params: {
363
+ id: Id;
364
+ oauth: OAuthProof;
365
+ nonce: bigint;
366
+ deadline: bigint;
367
+ }): Promise<RecipientSignature>;
296
368
  /**
297
369
  * POST /batch-claim-signature — 일괄 수령용 EIP-712 ValidatorClaim 서명.
298
370
  * nonce/deadline은 호출자가 정한다. nonce는 컨트랙트
@@ -308,25 +380,6 @@ interface SafeDropApiPort {
308
380
  }): Promise<BatchClaimSignature>;
309
381
  }
310
382
 
311
- /**
312
- * drops(claimAddr) 결과 매핑.
313
- *
314
- * ⚠️ 배포본마다 `drops`의 반환 필드 수가 다르다(permit 배포본은 5개 —
315
- * sponsor/amount/secretHash/salt/id). 그래서 `token`·`expiry`는 **optional**이다:
316
- * - `token` — 5필드 배포본에서는 에스크로의 `token()`으로 채운다(단일 토큰 고정).
317
- * - `expiry` — 5필드 배포본은 노출하지 않는다 → `undefined`. 만료 판정에 쓰기 전에
318
- * 존재 여부를 확인해야 한다(없다고 만료가 아니라, 알 수 없다는 뜻).
319
- */
320
- interface DropState {
321
- claimAddress: Address;
322
- sponsor: Address;
323
- token?: Address;
324
- amount: bigint;
325
- expiry?: number;
326
- secretHash: SecretHash;
327
- salt: Hex;
328
- id: Id;
329
- }
330
383
  /** Current ONEpop drop record, keyed by bytes32 rather than claim wallet. */
331
384
  interface OnePopDrop {
332
385
  dropKey: Hex;
@@ -337,6 +390,10 @@ interface OnePopDrop {
337
390
  secretHash: SecretHash;
338
391
  id: Id;
339
392
  }
393
+ interface DropState extends OnePopDrop {
394
+ /** ONEpop escrow is single-token; token() is contract-wide. */
395
+ token: Address;
396
+ }
340
397
  /**
341
398
  * SafeDrop 컨트랙트 상호작용. 어댑터는 자신의 컨트랙트 주소를 알고 있으므로
342
399
  * approve의 spender 등은 받지 않는다. 쓰기는 receipt 확인 후 tx hash 반환.
@@ -345,7 +402,7 @@ interface OnePopDrop {
345
402
  */
346
403
  interface SafeDropChainPort {
347
404
  getDropByKey(dropKey: Hex): Promise<OnePopDrop | null>;
348
- getDropKeyByClaimAddress(claimAddress: Address, sponsor?: Address): Promise<Hex | null>;
405
+ getDropKeyByClaimAddress(claimAddress: Address, sponsor: Address): Promise<Hex | null>;
349
406
  getClaimedRecipient(params: {
350
407
  id: Id;
351
408
  }): Promise<Address>;
@@ -358,36 +415,19 @@ interface SafeDropChainPort {
358
415
  getPendingDropsBySponsor(params: {
359
416
  sponsor: Address;
360
417
  }): Promise<readonly OnePopDrop[]>;
361
- /** drops(claimAddr). 없으면 null. */
362
- getDrop(claimAddress: Address): Promise<DropState | null>;
363
- /** claimDigest(recipient, id, salt) — 서명 대상 bytes32. */
418
+ /** activeDropOf(claimAddr) → drops(dropKey). 없으면 null. */
419
+ getDrop(claimAddress: Address, sponsor: Address): Promise<DropState | null>;
420
+ /** claimDigest(recipient, id, dropKey) — 서명 대상 bytes32. */
364
421
  getClaimDigest(params: {
365
422
  recipient: Address;
366
423
  id: Id;
367
- salt: Hex;
368
- }): Promise<Hex>;
369
- /** ERC20 approve (spender = SafeDrop 컨트랙트). 연결된 지갑이 서명. */
370
- approve(params: {
371
- token: Address;
372
- amount: bigint;
424
+ dropKey: Hex;
373
425
  }): Promise<Hex>;
374
- /** deposit(claimAddr, token, amount, id, secretHash). sponsor = msg.sender. */
375
- deposit(params: {
376
- claimAddress: Address;
377
- token: Address;
378
- amount: bigint;
379
- id: Id;
380
- secretHash: SecretHash;
381
- }): Promise<{
382
- txHash: Hex;
383
- }>;
384
426
  /**
385
- * EIP-2612 permit 예치 — approve tx 없이 서명 1회 + tx 1회로 끝낸다.
386
- * permit 예치를 지원하는 배포본에서만 구현되는 optional 경로: 존재하면
387
- * DepositUseCase가 approve+deposit 대신 이걸 쓴다.
427
+ * EIP-2612 permit 예치 — 현재 ONEpop deposit의 유일한 형태다.
388
428
  * 서명(typed data)·deadline·v/r/s는 전부 어댑터 내부 관심사다.
389
429
  */
390
- depositWithPermit?(params: {
430
+ depositWithPermit(params: {
391
431
  claimAddress: Address;
392
432
  token: Address;
393
433
  amount: bigint;
@@ -405,25 +445,13 @@ interface SafeDropChainPort {
405
445
  }): Promise<{
406
446
  txHash: Hex;
407
447
  }>;
408
- /**
409
- * withdraw(recipient, id, salt, signature, secret). claimAddr는 서명 recover로
410
- * 도출. tx는 claimKey 임시 지갑이 직접 전송 — estimateGas 없이 고정 gas +
411
- * dynamic fee(type-2)로 보내 컨트랙트 gas-abstraction 대납을 받는다.
412
- */
413
- withdraw(params: {
414
- claimKey: Hex;
415
- recipient: Address;
416
- id: Id;
417
- salt: Hex;
418
- signature: Hex;
419
- secret: Secret;
420
- }): Promise<Hex>;
421
448
  withdrawUnmapped(params: {
422
449
  claimKey: Hex;
423
450
  recipient: Address;
424
451
  id: Id;
425
452
  dropKey: Hex;
426
453
  secret: Secret;
454
+ signature?: Hex;
427
455
  onSubmitted?: (txHash: Hex) => void | Promise<void>;
428
456
  }): Promise<Hex>;
429
457
  withdrawMapped(params: {
@@ -433,9 +461,19 @@ interface SafeDropChainPort {
433
461
  batchWithdrawMapped(params: {
434
462
  count: number;
435
463
  }): Promise<Hex>;
436
- /** refund(claimAddr). 만료 후 sponsor(msg.sender)만. */
437
- refund(params: {
438
- claimAddress: Address;
464
+ batchWithdrawMappedByKeys(params: {
465
+ dropKeys: readonly Hex[];
466
+ }): Promise<Hex>;
467
+ withdrawUnmappedBatchByKeys(params: {
468
+ claimKey: Hex;
469
+ recipient: Address;
470
+ id: Id;
471
+ anchorDropKey: Hex;
472
+ secret: Secret;
473
+ nonce: bigint;
474
+ deadline: bigint;
475
+ dropKeys: readonly Hex[];
476
+ validatorSignature: Hex;
439
477
  }): Promise<Hex>;
440
478
  refundByKey(params: {
441
479
  dropKey: Hex;
@@ -443,6 +481,22 @@ interface SafeDropChainPort {
443
481
  getChangeNonce(params: {
444
482
  id: Id;
445
483
  }): Promise<bigint>;
484
+ getPendingRecipientChange(params: {
485
+ id: Id;
486
+ }): Promise<Address>;
487
+ requestRecipientChange(params: {
488
+ id: Id;
489
+ newRecipient: Address;
490
+ }): Promise<Hex>;
491
+ completeRecipientChange(params: {
492
+ id: Id;
493
+ nonce: bigint;
494
+ deadline: bigint;
495
+ signature: Hex;
496
+ }): Promise<Hex>;
497
+ cancelRecipientChange(params: {
498
+ id: Id;
499
+ }): Promise<Hex>;
446
500
  resetRecipient(params: {
447
501
  id: Id;
448
502
  nonce: bigint;
@@ -465,23 +519,6 @@ interface SafeDropChainPort {
465
519
  }): Promise<Hex>;
466
520
  /** validator() — 서명자여야 하는 주소. 백엔드 서명 검증의 기준값. */
467
521
  getValidator?(): Promise<Address>;
468
- /** liveDropCountById(id) — 남은 수령 대기 건수(페이지네이션 종료 조건). */
469
- getLiveDropCount?(params: {
470
- id: Id;
471
- }): Promise<bigint>;
472
- /**
473
- * withdrawByValidator(recipient, id, nonce, deadline, maxCount, signature).
474
- * tx는 **수령인 본인 지갑**이 보낸다(컨트랙트가 msg.sender와 서명의 recipient를
475
- * 대조). `maxCount`는 서명 대상이 아니라 페이지 크기다 — 같은 서명을 재사용한다.
476
- */
477
- withdrawByValidator?(params: {
478
- recipient: Address;
479
- id: Id;
480
- nonce: bigint;
481
- deadline: bigint;
482
- maxCount: number;
483
- signature: Hex;
484
- }): Promise<Hex>;
485
522
  }
486
523
 
487
524
  /**
@@ -503,7 +540,8 @@ interface ClaimSignerPort {
503
540
  * { claimBaseUrl },
504
541
  * { api, chain, signer, crypto },
505
542
  * );
506
- * const { withdrawLink, claimAddress } = await safeDrop.deposit({ ... });
543
+ * const result = await safeDrop.deposit({ ... });
544
+ * if (!result.isMapped) sendLink(result.withdrawLink);
507
545
  *
508
546
  * viem/HTTP 어댑터를 자동 조립하려면 `@nexus-cross/pop/adapters`의
509
547
  * createSafeDropClient를 사용한다. (도메인/컨트랙트 주소는 chain 어댑터가 안다.)
@@ -536,10 +574,10 @@ interface SafeDrop {
536
574
  }>;
537
575
  withdraw(params: WithdrawParams): Promise<WithdrawResult>;
538
576
  refund(params: RefundParams): Promise<RefundResult>;
539
- /** 온체인 드롭 상태 (drops(claimAddr)). 없으면 null. */
540
- getDrop(claimAddress: Address): Promise<DropState | null>;
577
+ /** activeDropOf(claimAddr)로 조회한 현재 온체인 드롭. */
578
+ getDrop(claimAddress: Address, sponsor: Address): Promise<DropState | null>;
541
579
  getDropByKey(dropKey: Hex): Promise<OnePopDrop | null>;
542
- getDropKeyByClaimAddress(claimAddress: Address, sponsor?: Address): Promise<Hex | null>;
580
+ getDropKeyByClaimAddress(claimAddress: Address, sponsor: Address): Promise<Hex | null>;
543
581
  getClaimedRecipient(id: Id): Promise<Address>;
544
582
  getPendingDropsById(id: Id): Promise<readonly OnePopDrop[]>;
545
583
  getPendingDropsByRecipient(recipient: Address): Promise<readonly OnePopDrop[]>;
@@ -547,8 +585,13 @@ interface SafeDrop {
547
585
  withdrawUnmapped(params: Parameters<SafeDropChainPort['withdrawUnmapped']>[0]): Promise<Hex>;
548
586
  withdrawMapped(params: Parameters<SafeDropChainPort['withdrawMapped']>[0]): Promise<Hex>;
549
587
  batchWithdrawMapped(count: number): Promise<Hex>;
588
+ batchWithdrawMappedByKeys(dropKeys: readonly Hex[]): Promise<Hex>;
550
589
  refundByKey(dropKey: Hex): Promise<Hex>;
551
590
  getChangeNonce(id: Id): Promise<bigint>;
591
+ getPendingRecipientChange(id: Id): Promise<Address>;
592
+ requestRecipientChange(id: Id, newRecipient: Address): Promise<Hex>;
593
+ completeRecipientChange(params: Parameters<SafeDropChainPort['completeRecipientChange']>[0]): Promise<Hex>;
594
+ cancelRecipientChange(id: Id): Promise<Hex>;
552
595
  resetRecipient(params: Parameters<SafeDropChainPort['resetRecipient']>[0]): Promise<Hex>;
553
596
  /** 내게 온 수령 대기 목록. Bearer JWT + 활성 X 연결 필요. */
554
597
  listDrops(params?: {
@@ -561,10 +604,17 @@ interface SafeDrop {
561
604
  /** 토큰별 pending 잔액 상위 (공개). */
562
605
  getLeaderboard(params: {
563
606
  token: Address;
564
- }): Promise<readonly LeaderboardEntry[]>;
565
- /** 내 온체인 이벤트 히스토리. Bearer JWT 필요. */
566
- listHistories(params?: {
567
- event?: PopEventName;
607
+ page?: number;
608
+ pageSize?: number;
609
+ identifier?: string;
610
+ }): Promise<LeaderboardPage>;
611
+ getMyLeaderboardEntry(params: {
612
+ token: Address;
613
+ }): Promise<MyLeaderboardEntry>;
614
+ /** sent/received 드롭 히스토리. Bearer JWT 필요. */
615
+ listHistories(params: {
616
+ type: HistoryType;
617
+ token?: Address;
568
618
  page?: number;
569
619
  pageSize?: number;
570
620
  }): Promise<HistoryPage>;
@@ -576,9 +626,26 @@ interface SafeDrop {
576
626
  }): Promise<XConnection>;
577
627
  /** X 연결 해제 (idempotent). */
578
628
  disconnectX(): Promise<void>;
629
+ submitFeedback(params: {
630
+ dropId: number;
631
+ message: string;
632
+ }): Promise<string>;
633
+ setRevealYou(revealYou: boolean): Promise<boolean>;
634
+ requestRecipientChangeSignature(params: {
635
+ id: Id;
636
+ oauth: OAuthProof;
637
+ nonce: bigint;
638
+ deadline: bigint;
639
+ }): Promise<RecipientChangeSignature>;
640
+ requestRecipientResetSignature(params: {
641
+ id: Id;
642
+ oauth: OAuthProof;
643
+ nonce: bigint;
644
+ deadline: bigint;
645
+ }): Promise<RecipientSignature>;
579
646
  /**
580
- * 일괄 수령 — nonce 조회 → 백엔드 서명 → **가스 전 서명 검증** → 전량 회수까지
581
- * 한 번에. tx는 연결된 수령인 지갑이 보낸다(secret 불필요).
647
+ * anchor drop의 secret/claim key와 validator 서명을 함께 사용해 현재 pending key를
648
+ * 한 번에 수령한다.
582
649
  */
583
650
  batchClaim(params: BatchClaimParams): Promise<BatchClaimResult>;
584
651
  /**
@@ -594,4 +661,4 @@ interface SafeDrop {
594
661
  }
595
662
  declare function createSafeDrop(config: SafeDropConfig, deps: SafeDropDeps): SafeDrop;
596
663
 
597
- export { type Address as A, type BatchClaimParams as B, type CryptoPort as C, type DepositParams as D, type Envelope as E, type Hex as H, type Id as I, type LeaderboardEntry as L, type OAuthProof as O, type PendingDrop as P, type RefundParams as R, type SafeDropChainPort as S, type WithdrawParams as W, type XConnection as X, type SafeDropApiPort as a, type DepositResult as b, type BatchClaimResult as c, type ClaimSignerPort as d, type WithdrawResult as e, type RefundResult as f, type Secret as g, type BatchClaimSignature as h, type DropInbox as i, type DropSender as j, type DropState as k, type HistoryEntry as l, type HistoryPage as m, type OnePopDrop as n, type PopEventName as o, type SafeDrop as p, type SafeDropConfig as q, type SafeDropDeps as r, SafeDropError as s, type SafeDropErrorCode as t, type SecretHash as u, type SocialIdentifier as v, type SocialProvider as w, createSafeDrop as x };
664
+ export { type Address as A, type BatchClaimParams as B, type CryptoPort as C, type DepositParams as D, type Envelope as E, type SocialIdentifier as F, type SocialProvider as G, type Hex as H, type Id as I, createSafeDrop as J, type LeaderboardEntry as L, type MappedDepositResult as M, type OAuthProof as O, type PendingDrop as P, type RefundParams as R, type SafeDropChainPort as S, type UnmappedDepositResult as U, type WithdrawParams as W, type XConnection as X, type SafeDropApiPort as a, type DepositResult as b, type BatchClaimResult as c, type ClaimSignerPort as d, type WithdrawResult as e, type RefundResult as f, type Secret as g, type BatchClaimSignature as h, type DropInbox as i, type DropSender as j, type DropState as k, type HistoryEntry as l, type HistoryPage as m, type HistoryParty as n, type HistoryType as o, type LeaderboardPage as p, type MyLeaderboardEntry as q, type OnePopDrop as r, type RecipientChangeSignature as s, type RecipientSignature as t, type SafeDrop as u, type SafeDropConfig as v, type SafeDropDeps as w, SafeDropError as x, type SafeDropErrorCode as y, type SecretHash as z };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,10 @@
1
- import { S as SafeDropChainPort, a as SafeDropApiPort, C as CryptoPort, D as DepositParams, b as DepositResult, B as BatchClaimParams, c as BatchClaimResult, d as ClaimSignerPort, W as WithdrawParams, e as WithdrawResult, R as RefundParams, f as RefundResult, A as Address, g as Secret } from './createSafeDrop-BSO9RQBD.js';
2
- export { h as BatchClaimSignature, i as DropInbox, j as DropSender, k as DropState, E as Envelope, H as Hex, l as HistoryEntry, m as HistoryPage, I as Id, L as LeaderboardEntry, O as OAuthProof, n as OnePopDrop, P as PendingDrop, o as PopEventName, p as SafeDrop, q as SafeDropConfig, r as SafeDropDeps, s as SafeDropError, t as SafeDropErrorCode, u as SecretHash, v as SocialIdentifier, w as SocialProvider, X as XConnection, x as createSafeDrop } from './createSafeDrop-BSO9RQBD.js';
1
+ import { S as SafeDropChainPort, a as SafeDropApiPort, C as CryptoPort, D as DepositParams, b as DepositResult, B as BatchClaimParams, c as BatchClaimResult, d as ClaimSignerPort, W as WithdrawParams, e as WithdrawResult, R as RefundParams, f as RefundResult, A as Address, g as Secret } from './createSafeDrop-CayUX4w_.js';
2
+ export { h as BatchClaimSignature, i as DropInbox, j as DropSender, k as DropState, E as Envelope, H as Hex, l as HistoryEntry, m as HistoryPage, n as HistoryParty, o as HistoryType, I as Id, L as LeaderboardEntry, p as LeaderboardPage, M as MappedDepositResult, q as MyLeaderboardEntry, O as OAuthProof, r as OnePopDrop, P as PendingDrop, s as RecipientChangeSignature, t as RecipientSignature, u as SafeDrop, v as SafeDropConfig, w as SafeDropDeps, x as SafeDropError, y as SafeDropErrorCode, z as SecretHash, F as SocialIdentifier, G as SocialProvider, U as UnmappedDepositResult, X as XConnection, J as createSafeDrop } from './createSafeDrop-CayUX4w_.js';
3
3
  export { X as XAuthPort, a as XTokenResult } from './XAuthPort-BNJePosj.js';
4
4
 
5
5
  /**
6
- * 예치: 임시 claim 지갑 생성 → secretHash 커밋 → (permit | approve) → deposit →
7
- * 수령 링크 생성. chain 어댑터가 depositWithPermit을 구현하면 approve tx를 생략한다.
6
+ * 예치: 임시 claim 지갑 생성 → secretHash 커밋 → permit deposit → 수령 링크 생성.
8
7
  * secret은 링크 fragment에만 담기고 어떤 포트로도 전송되지 않는다.
9
- * (expiry/salt는 컨트랙트가 결정.)
10
8
  */
11
9
  declare class DepositUseCase {
12
10
  private readonly chain;
@@ -18,55 +16,22 @@ declare class DepositUseCase {
18
16
  /** 수령 링크 base URL. */
19
17
  claimBaseUrl: string);
20
18
  execute(params: DepositParams): Promise<DepositResult>;
21
- /** permit 미지원 배포본: ERC20 approve tx → deposit tx. */
22
- private approveThenDeposit;
23
19
  }
24
20
 
25
- /**
26
- * 일괄 수령: 한 id에 쌓인 드롭 전부를 validator 서명 1건으로 회수한다.
27
- * 개별 수령과 달리 secret이 필요 없다 — 게이트는 validator 서명이다.
28
- *
29
- * 흐름 (온체인 계약이 정한 순서 그대로):
30
- * 1. nonce = validatorNonceById(keccak256(utf8(id))) ← id를 **해시**로 키잉
31
- * 2. 백엔드에 (id, nonce, deadline) + X 토큰으로 서명 요청
32
- * → recipient는 **응답값**을 쓴다(SIWE 주소에 바인딩되어 서명됨)
33
- * 3. digest = validatorClaimDigest(recipient, id, nonce, deadline) ← 온체인 값
34
- * recover(digest, signature) == validator() 인지 **가스 전에** 검증
35
- * 4. liveDropCountById(id)이 0이 될 때까지 withdrawByValidator(..., maxCount, sig)
36
- * 반복. maxCount는 서명 대상이 아니라 페이지 크기 → **서명 재사용**.
37
- *
38
- * 3번이 이 usecase의 존재 이유다: 백엔드가 다른 domain/type/nonce/recipient로
39
- * 서명하면 온체인에서는 `ECDSAInvalidSignature`로만 드러나 원인을 못 찾는다.
40
- */
21
+ /** Current ONEpop batch flow: one anchor claim proves the secret, validator authorizes one batch call. */
41
22
  declare class BatchClaimUseCase {
42
23
  private readonly chain;
43
24
  private readonly api;
44
25
  private readonly crypto;
45
- /** 테스트 주입용 시계. 기본 Date.now(). */
46
26
  private readonly now;
47
- constructor(chain: SafeDropChainPort, api: SafeDropApiPort, crypto: CryptoPort,
48
- /** 테스트 주입용 시계. 기본 Date.now(). */
49
- now?: () => number);
27
+ constructor(chain: SafeDropChainPort, api: SafeDropApiPort, crypto: CryptoPort, now?: () => number);
50
28
  execute(params: BatchClaimParams): Promise<BatchClaimResult>;
51
- /**
52
- * 일괄 수령의 목적지가 **개별 수령으로 이미 확정된 주소**인지 온체인에서 확인한다.
53
- * `claimedRecipientOf(id)`가 zero면 이 id는 아직 개별 수령을 하지 않은 상태 —
54
- * API의 `has_claimed_before` 게이트와 같은 조건이다(첫 수령은 개별로).
55
- * 어댑터가 이 read를 지원하지 않으면 검사를 생략한다(플로우는 유지).
56
- */
57
- private assertRecipientPinnedOnChain;
58
- /**
59
- * 사전 검증. `recoverAddress`가 없는 CryptoPort면 조용히 건너뛴다 — 최종 관문은
60
- * 어차피 컨트랙트이고, 이 검사는 "가스 쓰기 전에 원인을 알려주는" 용도다.
61
- */
62
29
  private assertSignedByValidator;
63
- private liveCount;
64
30
  }
65
31
 
66
32
  /**
67
- * 수령: drops(claimAddr)에서 id·salt 조회 → claimDigest 읽기 → 임시 키로 digest
68
- * raw 서명 → withdraw tx(임시 지갑이 직접 전송, 가스 대납). id/salt는 온체인
69
- * 드롭 값을 그대로 써서 IdMismatch/SaltMismatch를 원천 차단한다.
33
+ * 수령: activeDropOf(claimAddr)로 dropKey를 찾고 온체인 id로 claimDigest를 서명한 뒤
34
+ * withdrawUnmapped를 호출한다.
70
35
  */
71
36
  declare class WithdrawUseCase {
72
37
  private readonly chain;
@@ -75,7 +40,7 @@ declare class WithdrawUseCase {
75
40
  execute(params: WithdrawParams): Promise<WithdrawResult>;
76
41
  }
77
42
 
78
- /** 환불: 만료 후 sponsor(msg.sender)만 호출 가능. 만료/권한 검증은 컨트랙트가 최종 강제. */
43
+ /** claim address를 현재 drop key로 해석해 sponsor 환불을 실행한다. */
79
44
  declare class RefundUseCase {
80
45
  private readonly chain;
81
46
  constructor(chain: SafeDropChainPort);
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{a as r,b as e,c as o,d as t,e as p,f as a,g as s,h as i,i as f,j as m,k as n}from"./chunk-RS7SBR7A.js";export{i as BatchClaimUseCase,s as DepositUseCase,m as RefundUseCase,r as SafeDropError,f as WithdrawUseCase,a as buildComposeUrl,p as buildDmText,o as buildWithdrawLink,n as createSafeDrop,e as normalizeHandle,t as parseWithdrawLink};
1
+ import{a as r,b as e,c as o,d as t,e as p,f as a,g as s,h as i,i as f,j as n,k as m}from"./chunk-SE2HF5WH.js";export{i as BatchClaimUseCase,s as DepositUseCase,n as RefundUseCase,r as SafeDropError,f as WithdrawUseCase,a as buildComposeUrl,p as buildDmText,o as buildWithdrawLink,m as createSafeDrop,e as normalizeHandle,t as parseWithdrawLink};
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { p as SafeDrop } from '../createSafeDrop-BSO9RQBD.js';
3
+ import { u as SafeDrop } from '../createSafeDrop-CayUX4w_.js';
4
4
 
5
5
  interface SafeDropProviderProps {
6
6
  client: SafeDrop;