@nexus-cross/pop 1.4.0-beta.6 → 2.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.
- package/AGENTS.md +8 -1
- package/README.md +9 -1
- package/dist/{createSafeDrop-DtWLupoE.d.ts → SafeDropApiPort-BLewfSaK.d.ts} +1 -310
- package/dist/adapters/index.d.ts +6 -303
- package/dist/adapters/index.js +1 -1
- package/dist/api/index.d.ts +3 -0
- package/dist/api/index.js +1 -0
- package/dist/chunk-5DT3H2VX.js +1 -0
- package/dist/chunk-GS7GCYQD.js +1 -0
- package/dist/chunk-I7UGWJHZ.js +1 -0
- package/dist/createSafeDrop-DfiY8vHq.d.ts +312 -0
- package/dist/index-2sfHzZeD.d.ts +305 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1 -1
- package/dist/react/index.d.ts +2 -1
- package/package.json +5 -1
- package/dist/chunk-SX7PPVTJ.js +0 -1
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { m as SafeDropApiPort, A as Address, v as SocialIdentifier, I as Id, H as Hex, O as OAuthProof, e as DropInbox, E as Envelope, L as LeaderboardPage, M as MyLeaderboardEntry, f as HistoryType, g as HistoryStatus, h as HistoryPage, X as XConnection, i as RecipientChangeSignature, j as RecipientSignature, l as BatchClaimSignature } from './SafeDropApiPort-BLewfSaK.js';
|
|
2
|
+
import { X as XAuthPort, a as XTokenResult } from './XAuthPort-BNJePosj.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ONEpop 배포 설정 — API와 컨트랙트 주소를 동일한 환경 식별자로 선택한다.
|
|
6
|
+
* Vite import.meta.env + Next literal process.env 컨벤션을 따른다.
|
|
7
|
+
*
|
|
8
|
+
* 우선순위 (override):
|
|
9
|
+
* 1) `VITE_ONE_POP_API_BASE_URL` (Vite 빌드)
|
|
10
|
+
* 2) `NEXT_PUBLIC_ONE_POP_API_BASE_URL` (Next.js)
|
|
11
|
+
* 3) 환경 식별(`VITE_ONE_POP_ENVIRONMENT` / `NEXT_PUBLIC_ONE_POP_ENVIRONMENT`
|
|
12
|
+
* / `ONE_POP_ENVIRONMENT`)에 따라 DEFAULT_BASE_URL의 dev/stage/production
|
|
13
|
+
*
|
|
14
|
+
* 스펙: packages/pop/src/infrastructure/openapi.json (basePath `/api`)
|
|
15
|
+
*/
|
|
16
|
+
type PopEnvironment = 'dev' | 'stage' | 'production';
|
|
17
|
+
interface PopContracts {
|
|
18
|
+
onePop: `0x${string}`;
|
|
19
|
+
permitErc20: `0x${string}`;
|
|
20
|
+
nft: `0x${string}`;
|
|
21
|
+
nftMinter: `0x${string}`;
|
|
22
|
+
validator: `0x${string}`;
|
|
23
|
+
feeRecipient: `0x${string}`;
|
|
24
|
+
}
|
|
25
|
+
interface PopDeployment {
|
|
26
|
+
apiBaseUrl: string;
|
|
27
|
+
contracts?: PopContracts;
|
|
28
|
+
}
|
|
29
|
+
/** ONEpop protocol fee: 5% (500 / 10,000 basis points). */
|
|
30
|
+
declare const ONE_POP_FEE_BPS: bigint;
|
|
31
|
+
declare const ONE_POP_BPS_DENOMINATOR: bigint;
|
|
32
|
+
declare const ONE_POP_DEPLOYMENTS: Readonly<Record<PopEnvironment, PopDeployment>>;
|
|
33
|
+
interface PopApiPaths {
|
|
34
|
+
/** POST — 임시 claim 지갑 생성 (Bearer JWT). */
|
|
35
|
+
createWallet: string;
|
|
36
|
+
/** POST — tx hash에 메시지/봉투 메타데이터 연결 (Bearer JWT). */
|
|
37
|
+
dropMetadata: string;
|
|
38
|
+
/** POST — pending 지갑 개인키 수령 (X OAuth 토큰). */
|
|
39
|
+
retrievePrivateKey: string;
|
|
40
|
+
/** GET — 수령 대기 인박스 (Bearer JWT + 활성 X 연결). */
|
|
41
|
+
drops: string;
|
|
42
|
+
/** POST — pending 드롭 숨김 (Bearer JWT + 활성 X 연결). */
|
|
43
|
+
rejectDrops: string;
|
|
44
|
+
/** GET — 카드 디자인 목록 (공개). */
|
|
45
|
+
envelopes: string;
|
|
46
|
+
/** GET — 토큰별 pending 잔액 상위 (공개). */
|
|
47
|
+
leaderboards: string;
|
|
48
|
+
leaderboardMe: string;
|
|
49
|
+
/** GET — 내 온체인 이벤트 히스토리 (Bearer JWT). */
|
|
50
|
+
histories: string;
|
|
51
|
+
/** GET/POST/DELETE — X 연결 (Bearer JWT). */
|
|
52
|
+
xConnections: string;
|
|
53
|
+
/** POST — 일괄 수령 validator 서명 (Bearer JWT). */
|
|
54
|
+
batchClaimSignature: string;
|
|
55
|
+
feedbacks: string;
|
|
56
|
+
revealYou: string;
|
|
57
|
+
recipientChangeSignature: string;
|
|
58
|
+
recipientResetSignature: string;
|
|
59
|
+
/** GET — SSE 알림 스트림. pop은 구독하지 않는다(앱이 EventSource로 직접). */
|
|
60
|
+
eventsSubscribe: string;
|
|
61
|
+
}
|
|
62
|
+
declare const DEFAULT_POP_API_PATHS: PopApiPaths;
|
|
63
|
+
declare function getPopEnvironment(): PopEnvironment;
|
|
64
|
+
declare function resolvePopEnvironment(raw?: string): PopEnvironment;
|
|
65
|
+
declare function getOnePopDeployment(): PopDeployment;
|
|
66
|
+
declare function getOnePopContracts(): PopContracts;
|
|
67
|
+
/** 환경변수(override → 환경 식별)로 one-pop-api base URL을 결정한다. */
|
|
68
|
+
declare function getOnePopApiBaseUrl(): string;
|
|
69
|
+
/** 환경변수(override → 기본)로 cross-auth base URL을 결정한다. */
|
|
70
|
+
declare function getCrossAuthBaseUrl(): string;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* one-pop-api HTTP 어댑터. 스키마: packages/pop/src/infrastructure/openapi.json
|
|
74
|
+
* POST /wallets (Bearer JWT) → {address}
|
|
75
|
+
* POST /wallets/private-key (oauth_token 본문) → {address,private_key}
|
|
76
|
+
* GET /drops (Bearer JWT) → 수령 인박스
|
|
77
|
+
* POST /drops/reject (Bearer JWT) → 인박스에서 숨김
|
|
78
|
+
* GET /envelopes (공개) → 카드 디자인
|
|
79
|
+
* GET /leaderboards?token= (공개) → pending 상위
|
|
80
|
+
* GET /histories (Bearer JWT) → 온체인 이벤트
|
|
81
|
+
* GET|POST|DELETE /x-connections (Bearer JWT) → X 연결
|
|
82
|
+
* POST /batch-claim-signature (Bearer JWT) → ValidatorClaim 서명
|
|
83
|
+
*
|
|
84
|
+
* base URL은 미지정 시 환경변수로 결정(getOnePopApiBaseUrl).
|
|
85
|
+
* wei-scale 값은 응답의 10진 문자열 → BigInt로 변환해 내보낸다(CLAUDE.md §4).
|
|
86
|
+
*/
|
|
87
|
+
interface HttpSafeDropApiAdapterOptions {
|
|
88
|
+
/** 미지정 시 환경변수(VITE_/NEXT_PUBLIC_ONE_POP_*)로 결정. */
|
|
89
|
+
baseUrl?: string;
|
|
90
|
+
/** SIWE JWT 공급자. Bearer 인증이 필요한 모든 호출이 사용한다. */
|
|
91
|
+
getJwt?: () => string | undefined | Promise<string | undefined>;
|
|
92
|
+
/** 테스트/SSR용 fetch 주입. 기본 globalThis.fetch. */
|
|
93
|
+
fetchImpl?: typeof fetch;
|
|
94
|
+
/** 엔드포인트 경로 override. 기본 DEFAULT_POP_API_PATHS. */
|
|
95
|
+
paths?: Partial<PopApiPaths>;
|
|
96
|
+
}
|
|
97
|
+
declare class HttpSafeDropApiAdapter implements SafeDropApiPort {
|
|
98
|
+
private readonly baseUrl;
|
|
99
|
+
private readonly fetchImpl;
|
|
100
|
+
private readonly getJwt?;
|
|
101
|
+
private readonly paths;
|
|
102
|
+
constructor(options?: HttpSafeDropApiAdapterOptions);
|
|
103
|
+
createClaimWallet(params: {
|
|
104
|
+
sender: Address;
|
|
105
|
+
recipient: SocialIdentifier;
|
|
106
|
+
}): Promise<{
|
|
107
|
+
claimAddress: Address;
|
|
108
|
+
id: Id;
|
|
109
|
+
isMapped: boolean;
|
|
110
|
+
}>;
|
|
111
|
+
recordDropMetadata(params: {
|
|
112
|
+
txHash: Hex;
|
|
113
|
+
message?: string;
|
|
114
|
+
envelopeId?: string;
|
|
115
|
+
}): Promise<void>;
|
|
116
|
+
retrieveClaimKey(params: {
|
|
117
|
+
claimAddress: Address;
|
|
118
|
+
senderAddress: Address;
|
|
119
|
+
oauth: OAuthProof;
|
|
120
|
+
}): Promise<{
|
|
121
|
+
isMapped: true;
|
|
122
|
+
} | {
|
|
123
|
+
isMapped: false;
|
|
124
|
+
claimKey: Hex;
|
|
125
|
+
claimAddress: Address;
|
|
126
|
+
}>;
|
|
127
|
+
listDrops(params: {
|
|
128
|
+
token: Address;
|
|
129
|
+
dropKey?: Hex;
|
|
130
|
+
}): Promise<DropInbox>;
|
|
131
|
+
rejectDrops(params: {
|
|
132
|
+
dropIds: readonly number[];
|
|
133
|
+
}): Promise<number>;
|
|
134
|
+
listEnvelopes(params?: {
|
|
135
|
+
locale?: string;
|
|
136
|
+
}): Promise<readonly Envelope[]>;
|
|
137
|
+
getLeaderboard(params: {
|
|
138
|
+
token: Address;
|
|
139
|
+
page?: number;
|
|
140
|
+
pageSize?: number;
|
|
141
|
+
identifier?: string;
|
|
142
|
+
}): Promise<LeaderboardPage>;
|
|
143
|
+
getMyLeaderboardEntry(params: {
|
|
144
|
+
token: Address;
|
|
145
|
+
}): Promise<MyLeaderboardEntry>;
|
|
146
|
+
listHistories(params: {
|
|
147
|
+
type: HistoryType;
|
|
148
|
+
token?: Address;
|
|
149
|
+
status?: HistoryStatus;
|
|
150
|
+
rejected?: boolean;
|
|
151
|
+
page?: number;
|
|
152
|
+
pageSize?: number;
|
|
153
|
+
}): Promise<HistoryPage>;
|
|
154
|
+
getXConnection(): Promise<XConnection | null>;
|
|
155
|
+
connectX(params: {
|
|
156
|
+
oauth: OAuthProof;
|
|
157
|
+
}): Promise<XConnection>;
|
|
158
|
+
disconnectX(): Promise<void>;
|
|
159
|
+
submitFeedback(params: {
|
|
160
|
+
dropId: number;
|
|
161
|
+
message: string;
|
|
162
|
+
}): Promise<string>;
|
|
163
|
+
setRevealYou(params: {
|
|
164
|
+
revealYou: boolean;
|
|
165
|
+
}): Promise<boolean>;
|
|
166
|
+
requestRecipientChangeSignature(params: {
|
|
167
|
+
id: Id;
|
|
168
|
+
oauth: OAuthProof;
|
|
169
|
+
nonce: bigint;
|
|
170
|
+
deadline: bigint;
|
|
171
|
+
}): Promise<RecipientChangeSignature>;
|
|
172
|
+
requestRecipientResetSignature(params: {
|
|
173
|
+
id: Id;
|
|
174
|
+
oauth: OAuthProof;
|
|
175
|
+
nonce: bigint;
|
|
176
|
+
deadline: bigint;
|
|
177
|
+
}): Promise<RecipientSignature>;
|
|
178
|
+
requestBatchClaimSignature(params: {
|
|
179
|
+
id: Id;
|
|
180
|
+
oauth: OAuthProof;
|
|
181
|
+
nonce: bigint;
|
|
182
|
+
deadline: bigint;
|
|
183
|
+
}): Promise<BatchClaimSignature>;
|
|
184
|
+
private request;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* cross-auth SIWE 로그인 클라이언트. createClaimWallet에 필요한 플랫폼 JWT를 얻는다.
|
|
189
|
+
* 1) unsignedHash(chainId, address) → { hash, message }
|
|
190
|
+
* 2) 앱이 지갑으로 message 서명(signMessage)
|
|
191
|
+
* 3) siweToken(address, signature) → { token, refresh }
|
|
192
|
+
*
|
|
193
|
+
* 서명은 앱(wagmi/walletClient)이 수행 — 이 클라이언트는 HTTP만 담당한다.
|
|
194
|
+
* domain은 cross-auth가 SIWE domain으로 사용(기본 window.location.origin).
|
|
195
|
+
*/
|
|
196
|
+
interface CrossAuthClientOptions {
|
|
197
|
+
/** 미지정 시 환경변수(VITE_/NEXT_PUBLIC_CROSS_AUTH_URL) 또는 dev 기본값. */
|
|
198
|
+
baseUrl?: string;
|
|
199
|
+
/** SIWE domain. 미지정 시 globalThis.location.origin. */
|
|
200
|
+
domain?: string;
|
|
201
|
+
fetchImpl?: typeof fetch;
|
|
202
|
+
}
|
|
203
|
+
declare class CrossAuthClient {
|
|
204
|
+
private readonly baseUrl;
|
|
205
|
+
private readonly domain;
|
|
206
|
+
private readonly fetchImpl;
|
|
207
|
+
constructor(options?: CrossAuthClientOptions);
|
|
208
|
+
/** SIWE 서명 대상 메시지 발급. cross-auth 필드는 snake_case `chain_id`. */
|
|
209
|
+
unsignedHash(chainId: number, address: string): Promise<{
|
|
210
|
+
hash: string;
|
|
211
|
+
message: string;
|
|
212
|
+
}>;
|
|
213
|
+
/** 서명 → 플랫폼 JWT 교환. */
|
|
214
|
+
siweToken(address: string, signature: string): Promise<{
|
|
215
|
+
token: string;
|
|
216
|
+
refresh: string;
|
|
217
|
+
}>;
|
|
218
|
+
private post;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
interface Pkce {
|
|
222
|
+
verifier: string;
|
|
223
|
+
challenge: string;
|
|
224
|
+
method: 'S256';
|
|
225
|
+
}
|
|
226
|
+
/** code_verifier(43자) + S256 code_challenge 생성. */
|
|
227
|
+
declare function generatePkce(): Promise<Pkce>;
|
|
228
|
+
/** CSRF 방지용 state (base64url 22자). */
|
|
229
|
+
declare function generateState(): string;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* X OAuth2 프록시 어댑터. 앱의 same-origin Next 라우트를 호출한다(one-pop-fe와 동일 계약).
|
|
233
|
+
* POST {tokenPath} { clientId, redirectUri, code, verifier } → X 토큰 응답(access_token)
|
|
234
|
+
* GET {mePath} Authorization: Bearer <token> → GET /2/users/me ({ data: { username } })
|
|
235
|
+
*
|
|
236
|
+
* 프록시가 grant_type/Basic auth 조립과 X API 응답 전달을 담당한다. 다르면 옵션으로 경로만 조정.
|
|
237
|
+
*/
|
|
238
|
+
interface HttpXAuthAdapterOptions {
|
|
239
|
+
/** 프록시 base URL. 기본 '' (same-origin 상대경로). */
|
|
240
|
+
baseUrl?: string;
|
|
241
|
+
/** 토큰 교환 프록시 경로. 기본 '/api/x/token'. */
|
|
242
|
+
tokenPath?: string;
|
|
243
|
+
/** 핸들 조회 프록시 경로. 기본 '/api/x/me'. */
|
|
244
|
+
mePath?: string;
|
|
245
|
+
fetchImpl?: typeof fetch;
|
|
246
|
+
}
|
|
247
|
+
declare class HttpXAuthAdapter implements XAuthPort {
|
|
248
|
+
private readonly baseUrl;
|
|
249
|
+
private readonly tokenPath;
|
|
250
|
+
private readonly mePath;
|
|
251
|
+
private readonly fetchImpl;
|
|
252
|
+
constructor(options?: HttpXAuthAdapterOptions);
|
|
253
|
+
exchangeCode(params: {
|
|
254
|
+
clientId: string;
|
|
255
|
+
redirectUri: string;
|
|
256
|
+
code: string;
|
|
257
|
+
codeVerifier: string;
|
|
258
|
+
}): Promise<XTokenResult>;
|
|
259
|
+
getHandle(accessToken: string): Promise<{
|
|
260
|
+
handle: string;
|
|
261
|
+
}>;
|
|
262
|
+
private call;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** verifier/state 임시 보관. 기본은 sessionStorage 어댑터. */
|
|
266
|
+
interface SessionStore {
|
|
267
|
+
get(key: string): string | null;
|
|
268
|
+
set(key: string, value: string): void;
|
|
269
|
+
remove(key: string): void;
|
|
270
|
+
}
|
|
271
|
+
interface XAuthClientOptions {
|
|
272
|
+
clientId: string;
|
|
273
|
+
redirectUri: string;
|
|
274
|
+
/** 기본 'tweet.read users.read offline.access' (GET /2/users/me + refresh token). */
|
|
275
|
+
scope?: string;
|
|
276
|
+
/** 기본 X authorize 엔드포인트. */
|
|
277
|
+
authorizeUrl?: string;
|
|
278
|
+
/** 토큰 교환/핸들 조회 프록시 어댑터. */
|
|
279
|
+
port: XAuthPort;
|
|
280
|
+
/** 기본 globalThis.sessionStorage 어댑터. */
|
|
281
|
+
storage?: SessionStore;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* X OAuth2 PKCE 플로우. UI/리다이렉트는 앱이 담당한다:
|
|
285
|
+
* const { authorizeUrl } = await xauth.start(); location.assign(authorizeUrl);
|
|
286
|
+
* // 콜백에서:
|
|
287
|
+
* const { oauth, handle } = await xauth.complete(location.href);
|
|
288
|
+
* await safeDrop.retrieveClaimKey({ senderAddress, oauth });
|
|
289
|
+
*/
|
|
290
|
+
declare class XAuthClient {
|
|
291
|
+
private readonly opts;
|
|
292
|
+
constructor(options: XAuthClientOptions);
|
|
293
|
+
/** PKCE·state 생성·저장 후 X authorize URL 반환. 리다이렉트는 호출자 몫. */
|
|
294
|
+
start(): Promise<{
|
|
295
|
+
authorizeUrl: string;
|
|
296
|
+
state: string;
|
|
297
|
+
}>;
|
|
298
|
+
/** 콜백 URL에서 code/state 추출 → state 검증 → 토큰 교환 → 핸들 조회. */
|
|
299
|
+
complete(callbackUrl: string): Promise<{
|
|
300
|
+
oauth: OAuthProof;
|
|
301
|
+
handle: string;
|
|
302
|
+
}>;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export { CrossAuthClient as C, DEFAULT_POP_API_PATHS as D, type HttpSafeDropApiAdapterOptions as H, ONE_POP_BPS_DENOMINATOR as O, type Pkce as P, type SessionStore as S, XAuthClient as X, type CrossAuthClientOptions as a, HttpSafeDropApiAdapter as b, HttpXAuthAdapter as c, type HttpXAuthAdapterOptions as d, ONE_POP_DEPLOYMENTS as e, ONE_POP_FEE_BPS as f, type PopApiPaths as g, type PopContracts as h, type PopDeployment as i, type PopEnvironment as j, type XAuthClientOptions as k, generatePkce as l, generateState as m, getCrossAuthBaseUrl as n, getOnePopApiBaseUrl as o, getOnePopContracts as p, getOnePopDeployment as q, getPopEnvironment as r, resolvePopEnvironment as s };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { m as SafeDropApiPort, D as DepositParams, b as DepositResult, B as BatchClaimParams, k as BatchClaimResult, W as WithdrawParams, c as WithdrawResult, R as RefundParams, d as RefundResult, A as Address, S as Secret } from './SafeDropApiPort-BLewfSaK.js';
|
|
2
|
+
export { l as BatchClaimSignature, e as DropInbox, n as DropSender, E as Envelope, H as Hex, o as HistoryEntry, h as HistoryPage, p as HistoryParty, q as HistoryReceiverParty, g as HistoryStatus, f as HistoryType, I as Id, r as LeaderboardEntry, L as LeaderboardPage, s as MappedDepositResult, M as MyLeaderboardEntry, O as OAuthProof, P as PendingDrop, i as RecipientChangeSignature, j as RecipientSignature, t as SafeDropError, u as SafeDropErrorCode, a as SecretHash, v as SocialIdentifier, w as SocialProvider, U as UnmappedDepositResult, X as XConnection } from './SafeDropApiPort-BLewfSaK.js';
|
|
3
|
+
import { a as SafeDropChainPort, C as CryptoPort, b as ClaimSignerPort } from './createSafeDrop-DfiY8vHq.js';
|
|
4
|
+
export { D as DropState, O as OnePopDrop, S as SafeDrop, c as SafeDropConfig, d as SafeDropDeps, e as createSafeDrop } from './createSafeDrop-DfiY8vHq.js';
|
|
3
5
|
export { X as XAuthPort, a as XTokenResult } from './XAuthPort-BNJePosj.js';
|
|
4
6
|
|
|
5
7
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as
|
|
1
|
+
import{a as e,b as o,c as t,d as p,e as a,f as s,g as i,h as f,i as n,j as m}from"./chunk-GS7GCYQD.js";import{a as r}from"./chunk-5DT3H2VX.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};
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { S as SafeDrop } from '../createSafeDrop-DfiY8vHq.js';
|
|
4
|
+
import '../SafeDropApiPort-BLewfSaK.js';
|
|
4
5
|
|
|
5
6
|
interface SafeDropProviderProps {
|
|
6
7
|
client: SafeDrop;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexus-cross/pop",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.4.0-beta.2",
|
|
4
4
|
"description": "pop — framework-agnostic core + React adapter.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
"types": "./dist/adapters/index.d.ts",
|
|
19
19
|
"import": "./dist/adapters/index.js"
|
|
20
20
|
},
|
|
21
|
+
"./api": {
|
|
22
|
+
"types": "./dist/api/index.d.ts",
|
|
23
|
+
"import": "./dist/api/index.js"
|
|
24
|
+
},
|
|
21
25
|
"./AGENTS.md": "./AGENTS.md",
|
|
22
26
|
"./openapi.json": "./src/infrastructure/openapi.json"
|
|
23
27
|
},
|
package/dist/chunk-SX7PPVTJ.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var i=class extends Error{constructor(e,r,n){super(r),this.name="SafeDropError",this.code=e,this.details=n}};function g(a){return a.trim().replace(/^@/,"").toLowerCase()}function w(a){let e=a.baseUrl.replace(/\/$/,""),r=e.includes("?")?"&":"?",n=a.claimAddress?`&claim=${encodeURIComponent(a.claimAddress)}`:"",s=`${e}${r}sender=${encodeURIComponent(a.sender)}${n}`;return a.secret?`${s}#${encodeURIComponent(a.secret)}`:s}function b(a){let e=a.indexOf("#"),r=e===-1?a:a.slice(0,e),n=e===-1?"":a.slice(e+1),s=r.indexOf("?"),d=s===-1?"":r.slice(s+1);return{sender:A(d,"sender"),secret:n?decodeURIComponent(n):null}}function H(a){return`\u{1F381} You've received a one-pop drop! Claim your tokens here: ${a}`}function M(a,e){let r=[`text=${encodeURIComponent(a)}`];return e&&r.push(`recipient_id=${encodeURIComponent(e)}`),`https://x.com/messages/compose?${r.join("&")}`}function A(a,e){if(!a)return null;for(let r of a.split("&")){if(!r)continue;let n=r.indexOf("=");if(decodeURIComponent(n===-1?r:r.slice(0,n))===e)return decodeURIComponent(n===-1?"":r.slice(n+1))}return null}var y=class{constructor(e,r,n,s){this.chain=e;this.api=r;this.crypto=n;this.claimBaseUrl=s}async execute(e){if(!e.sender)throw new i("MISSING_SENDER","sender address is required");if(!e.recipient?.handle)throw new i("MISSING_RECIPIENT","recipient social handle is required");if(!e.token)throw new i("INVALID_TOKEN","token address is required (ERC20 only)");if(e.amount<=0n)throw new i("INVALID_AMOUNT","amount must be a positive BigInt");if(e.message&&[...e.message].length>140)throw new i("INVALID_PARAM","message must be <= 140 runes");let r=g(e.recipient.handle);if(!r)throw new i("MISSING_RECIPIENT","recipient handle normalizes to empty");let n=await this.api.createClaimWallet({sender:e.sender,recipient:{...e.recipient,handle:r}}),s=n.id,d=async m=>{if(this.api.recordDropMetadata)try{await this.api.recordDropMetadata({txHash:m,message:e.message,envelopeId:e.envelopeId})}catch(c){if(c instanceof i&&c.details?.codeName==="ENVELOPE_NOT_FOUND"&&e.envelopeId)try{await this.api.recordDropMetadata({txHash:m,message:e.message})}catch{}}};if(n.isMapped){let{txHash:m,dropKey:c}=await this.chain.depositMapped({token:e.token,amount:e.amount,id:s,onSubmitted:d});return{isMapped:!0,dropKey:c,depositTxHash:m}}let o=e.secret??this.crypto.randomSecret();if(!o)throw new i("MISSING_SECRET","secret is empty");let t=this.crypto.keccak256(o),l={claimAddress:n.claimAddress,token:e.token,amount:e.amount,id:s,secretHash:t,onSubmitted:d},{txHash:h,dropKey:u}=await this.chain.depositWithPermit(l);return{isMapped:!1,dropKey:u,claimAddress:n.claimAddress,secretHash:t,withdrawLink:w({baseUrl:this.claimBaseUrl,sender:e.sender,claimAddress:n.claimAddress,secret:o}),depositTxHash:h}}};var N=BigInt(1800),x=30,f=class{constructor(e,r,n,s=()=>Date.now()){this.chain=e;this.api=r;this.crypto=n;this.now=s}async execute(e){let r=g(e.id);if(!r)throw new i("MISSING_RECIPIENT","batchClaim requires an id");if(!e.claimAddress)throw new i("MISSING_CLAIM_ADDRESS","claim address is required");if(!e.sponsor)throw new i("MISSING_SENDER","sponsor address is required");if(!e.claimKey)throw new i("MISSING_CLAIM_KEY","claim key is required");if(!e.secret)throw new i("MISSING_SECRET","secret is required");if(!this.api.requestBatchClaimSignature)throw new i("API_ERROR","requestBatchClaimSignature is not implemented");if(!this.chain.getValidatorNonce||!this.chain.getValidatorClaimDigest||!this.chain.getValidator)throw new i("CHAIN_ERROR","validator reads are not implemented");let n=await this.chain.getDropKeyByClaimAddress(e.claimAddress,e.sponsor);if(!n)throw new i("DROP_NOT_FOUND","anchor drop not found");let s=await this.chain.getDropByKey(n);if(!s||s.id!==r)throw new i("DROP_NOT_FOUND","anchor drop id does not match");let d=await this.chain.getPendingDropsById({id:r});if(!d.length)throw new i("DROP_NOT_FOUND",`No pending drops for ${r}`);let o=e.maxCount??x;if(!Number.isSafeInteger(o)||o<=0)throw new i("INVALID_PARAM","maxCount must be a positive safe integer");let t=e.deadline??BigInt(Math.floor(this.now()/1e3))+(e.deadlineTtlSeconds??N),l=[],h="",u=BigInt(0);for(;d.length;){let m=await this.chain.getValidatorNonce({id:r}),c=await this.api.requestBatchClaimSignature({id:r,oauth:e.oauth,nonce:m,deadline:t});if(e.recipient&&e.recipient.toLowerCase()!==c.recipient.toLowerCase())throw new i("SIGN_FAILED","validator signature is bound to a different recipient");if(h&&h.toLowerCase()!==c.recipient.toLowerCase())throw new i("SIGN_FAILED","validator recipient changed between batches");h=c.recipient,l.length||(u=c.nonce);let I=await this.chain.getValidatorClaimDigest({recipient:h,id:r,nonce:c.nonce,deadline:c.deadline});await this.assertSignedByValidator(I,c.signature);let R=d.length,C=await this.chain.withdrawUnmappedBatchByKeys({claimKey:e.claimKey,recipient:h,id:r,anchorDropKey:n,secret:e.secret,nonce:c.nonce,deadline:c.deadline,dropKeys:d.slice(0,o).map(P=>P.dropKey).filter(P=>P.toLowerCase()!==n.toLowerCase()),validatorSignature:c.signature});if(l.push(C),d=await this.chain.getPendingDropsById({id:r}),d.length>=R)throw new i("CHAIN_ERROR","batch claim made no progress",{id:r,txHash:C})}return{txHashes:l,recipient:h,id:r,nonce:u,deadline:t}}async assertSignedByValidator(e,r){if(!this.crypto.recoverAddress||!this.chain.getValidator)return;let[n,s]=await Promise.all([this.crypto.recoverAddress({digest:e,signature:r}),this.chain.getValidator()]);if(n.toLowerCase()!==s.toLowerCase())throw new i("SIGN_FAILED","batch-claim signature does not recover to validator")}};var D=class{constructor(e,r){this.chain=e;this.signer=r}async execute(e){if(!e.recipient)throw new i("MISSING_RECIPIENT","recipient address is required");if(!e.claimAddress)throw new i("MISSING_CLAIM_ADDRESS","claim address is required");if(!e.secret)throw new i("MISSING_SECRET","secret is required");if(!e.claimKey)throw new i("MISSING_CLAIM_KEY","claim key is required");if(!e.sponsor)throw new i("MISSING_SENDER","sponsor address is required");let r=await this.chain.getDropKeyByClaimAddress(e.claimAddress,e.sponsor);if(!r)throw new i("DROP_NOT_FOUND",`No drop for claim address ${e.claimAddress}`);let n=await this.chain.getDropByKey(r);if(!n)throw new i("DROP_NOT_FOUND",`No drop for key ${r}`);let s=await this.chain.getClaimDigest({recipient:e.recipient,id:n.id,dropKey:r}),d=await this.signer.signDigest({claimKey:e.claimKey,digest:s});return{txHash:await this.chain.withdrawUnmapped({claimKey:e.claimKey,recipient:e.recipient,id:n.id,dropKey:r,signature:d,secret:e.secret})}}};var S=class{constructor(e){this.chain=e}async execute(e){if(!e.claimAddress)throw new i("MISSING_CLAIM_ADDRESS","claim address is required");if(!e.sponsor)throw new i("MISSING_SENDER","sponsor address is required");let r=await this.chain.getDropKeyByClaimAddress(e.claimAddress,e.sponsor);if(!r)throw new i("DROP_NOT_FOUND",`No drop for claim address ${e.claimAddress}`);return{txHash:await this.chain.refundByKey({dropKey:r})}}};function p(a,e){if(!a)throw new i("API_ERROR",`SafeDropApiPort.${e} is not implemented by the injected api adapter`);return a}function z(a,e){let r=new y(e.chain,e.api,e.crypto,a.claimBaseUrl),n=new D(e.chain,e.signer),s=new S(e.chain),d=new f(e.chain,e.api,e.crypto),{api:o}=e;return{config:a,deposit:t=>r.execute(t),retrieveClaimKey:t=>o.retrieveClaimKey(t),withdraw:t=>n.execute(t),refund:t=>s.execute(t),getDrop:(t,l)=>e.chain.getDrop(t,l),getDropByKey:t=>e.chain.getDropByKey(t),getDropKeyByClaimAddress:(t,l)=>e.chain.getDropKeyByClaimAddress(t,l),getClaimedRecipient:t=>e.chain.getClaimedRecipient({id:t}),getPendingDropsById:t=>e.chain.getPendingDropsById({id:t}),getPendingDropsByRecipient:t=>e.chain.getPendingDropsByRecipient({recipient:t}),getPendingDropsBySponsor:t=>e.chain.getPendingDropsBySponsor({sponsor:t}),withdrawUnmapped:t=>e.chain.withdrawUnmapped(t),withdrawMapped:t=>e.chain.withdrawMapped(t),batchWithdrawMapped:t=>e.chain.batchWithdrawMapped({count:t}),batchWithdrawMappedByKeys:t=>e.chain.batchWithdrawMappedByKeys({dropKeys:t}),refundByKey:t=>e.chain.refundByKey({dropKey:t}),getChangeNonce:t=>e.chain.getChangeNonce({id:t}),getPendingRecipientChange:t=>e.chain.getPendingRecipientChange({id:t}),requestRecipientChange:(t,l)=>e.chain.requestRecipientChange({id:t,newRecipient:l}),completeRecipientChange:t=>e.chain.completeRecipientChange(t),cancelRecipientChange:t=>e.chain.cancelRecipientChange({id:t}),resetRecipient:t=>e.chain.resetRecipient(t),listDrops:t=>p(o.listDrops,"listDrops").call(o,t),rejectDrops:t=>p(o.rejectDrops,"rejectDrops").call(o,{dropIds:t}),listEnvelopes:t=>p(o.listEnvelopes,"listEnvelopes").call(o,t),getLeaderboard:t=>p(o.getLeaderboard,"getLeaderboard").call(o,t),getMyLeaderboardEntry:t=>p(o.getMyLeaderboardEntry,"getMyLeaderboardEntry").call(o,t),listHistories:t=>p(o.listHistories,"listHistories").call(o,t),getXConnection:()=>p(o.getXConnection,"getXConnection").call(o),connectX:t=>p(o.connectX,"connectX").call(o,t),disconnectX:()=>p(o.disconnectX,"disconnectX").call(o),submitFeedback:t=>p(o.submitFeedback,"submitFeedback").call(o,t),setRevealYou:t=>p(o.setRevealYou,"setRevealYou").call(o,{revealYou:t}),requestRecipientChangeSignature:t=>p(o.requestRecipientChangeSignature,"requestRecipientChangeSignature").call(o,t),requestRecipientResetSignature:t=>p(o.requestRecipientResetSignature,"requestRecipientResetSignature").call(o,t),batchClaim:t=>d.execute(t),requestBatchClaimSignature:t=>p(o.requestBatchClaimSignature,"requestBatchClaimSignature").call(o,t)}}export{i as a,g as b,w as c,b as d,H as e,M as f,y as g,f as h,D as i,S as j,z as k};
|