@rhinestone/deposit-modal 0.8.1 → 0.9.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/README.md +193 -29
- package/dist/{chunk-2JPB3PLB.mjs → DepositModalReown-6KUAO5ZC.mjs} +56 -4
- package/dist/{chunk-Q3W53BKR.cjs → DepositModalReown-XC5RIU7Z.cjs} +62 -10
- package/dist/{caip-C_ZYFIGa.d.cts → caip-523Zrc3r.d.cts} +1 -3
- package/dist/{caip-C_ZYFIGa.d.ts → caip-523Zrc3r.d.ts} +1 -3
- package/dist/{chunk-D3Y7ZBED.cjs → chunk-22RV33LK.cjs} +2170 -1460
- package/dist/chunk-4WB2FHGC.mjs +865 -0
- package/dist/chunk-A223BLVC.mjs +801 -0
- package/dist/{chunk-HQWZCOMS.cjs → chunk-DIX7M3SP.cjs} +232 -601
- package/dist/{chunk-T43VUEJH.mjs → chunk-E4G5BOZP.mjs} +167 -536
- package/dist/chunk-H577RJN5.cjs +801 -0
- package/dist/{chunk-DABKCJVL.mjs → chunk-ILT2PITN.mjs} +60 -3
- package/dist/{chunk-7KHEIMWD.mjs → chunk-KKHLNFSA.mjs} +2436 -1726
- package/dist/chunk-LGVJWVSS.mjs +81 -0
- package/dist/chunk-NEXUCY4B.cjs +11 -0
- package/dist/chunk-NMIMRASD.cjs +1785 -0
- package/dist/chunk-OSI2CFGL.mjs +11 -0
- package/dist/chunk-PAGMU4RQ.cjs +865 -0
- package/dist/chunk-T7LGQFP3.cjs +81 -0
- package/dist/chunk-VN4BLZYC.cjs +2273 -0
- package/dist/chunk-VOGZAZB2.mjs +2273 -0
- package/dist/chunk-WYXBY2MQ.mjs +1785 -0
- package/dist/{chunk-4NN7UTWQ.cjs → chunk-YEBXUUH3.cjs} +63 -6
- package/dist/claim.cjs +10 -0
- package/dist/claim.d.cts +8 -0
- package/dist/claim.d.ts +8 -0
- package/dist/claim.mjs +10 -0
- package/dist/constants.cjs +3 -3
- package/dist/constants.d.cts +4 -2
- package/dist/constants.d.ts +4 -2
- package/dist/constants.mjs +5 -5
- package/dist/deposit.cjs +8 -6
- package/dist/deposit.d.cts +2 -2
- package/dist/deposit.d.ts +2 -2
- package/dist/deposit.mjs +7 -5
- package/dist/index.cjs +22 -12
- package/dist/index.d.cts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.mjs +21 -11
- package/dist/polymarket.cjs +5 -6
- package/dist/polymarket.mjs +2 -3
- package/dist/server.cjs +96 -0
- package/dist/server.d.cts +65 -0
- package/dist/server.d.ts +65 -0
- package/dist/server.mjs +96 -0
- package/dist/styles.css +263 -12
- package/dist/types-C0SGf-21.d.cts +606 -0
- package/dist/types-C0SGf-21.d.ts +606 -0
- package/dist/withdraw.cjs +6 -5
- package/dist/withdraw.d.cts +3 -6
- package/dist/withdraw.d.ts +3 -6
- package/dist/withdraw.mjs +5 -4
- package/package.json +53 -6
- package/dist/DepositModalReown-4BSHOQ5Y.mjs +0 -63
- package/dist/DepositModalReown-UND3DEJH.cjs +0 -63
- package/dist/WithdrawModalReown-FVXSSGY5.mjs +0 -46
- package/dist/WithdrawModalReown-TVZWJKQI.cjs +0 -46
- package/dist/chunk-7OKA6GNA.cjs +0 -4537
- package/dist/chunk-NASHLEVQ.mjs +0 -4537
- package/dist/chunk-O5OKA27M.mjs +0 -800
- package/dist/chunk-U7SVYWVD.cjs +0 -800
- package/dist/chunk-WK5AFRSP.mjs +0 -295
- package/dist/chunk-XRWQMIBY.cjs +0 -295
- package/dist/types--LQWg_4W.d.cts +0 -468
- package/dist/types--LQWg_4W.d.ts +0 -468
package/dist/server.cjs
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/server.ts
|
|
2
|
+
var DEFAULT_PROCESSOR_URL = "https://v1.orchestrator.rhinestone.dev/deposit-processor";
|
|
3
|
+
function jsonError(message, status) {
|
|
4
|
+
return new Response(JSON.stringify({ error: message }), {
|
|
5
|
+
status,
|
|
6
|
+
headers: { "Content-Type": "application/json" }
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
function parseBody(value) {
|
|
10
|
+
if (typeof value !== "object" || value === null) return null;
|
|
11
|
+
const record = value;
|
|
12
|
+
const fields = ["chain", "txHash", "account", "token", "destination"];
|
|
13
|
+
for (const field of fields) {
|
|
14
|
+
if (typeof record[field] !== "string" || record[field] === "") return null;
|
|
15
|
+
}
|
|
16
|
+
return Object.fromEntries(
|
|
17
|
+
fields.map((field) => [field, record[field]])
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
function sameIdentifier(a, b) {
|
|
21
|
+
if (a === b) return true;
|
|
22
|
+
const isHex = (value) => /^0x[0-9a-fA-F]+$/.test(value);
|
|
23
|
+
return isHex(a) && isHex(b) && a.toLowerCase() === b.toLowerCase();
|
|
24
|
+
}
|
|
25
|
+
function createRefundHandler(options) {
|
|
26
|
+
const processorUrl = (_nullishCoalesce(options.processorUrl, () => ( DEFAULT_PROCESSOR_URL))).replace(
|
|
27
|
+
/\/$/,
|
|
28
|
+
""
|
|
29
|
+
);
|
|
30
|
+
const headers = {
|
|
31
|
+
"Content-Type": "application/json",
|
|
32
|
+
"x-api-key": options.apiKey
|
|
33
|
+
};
|
|
34
|
+
return async function handleRefund(request) {
|
|
35
|
+
const body = parseBody(await request.json().catch(() => null));
|
|
36
|
+
if (!body) {
|
|
37
|
+
return jsonError("Malformed refund request", 400);
|
|
38
|
+
}
|
|
39
|
+
const authorization = await options.authorize(request, body);
|
|
40
|
+
if (!authorization) {
|
|
41
|
+
return jsonError("Unauthorized", 401);
|
|
42
|
+
}
|
|
43
|
+
const query = new URLSearchParams({
|
|
44
|
+
recipient: authorization.depositRecipient,
|
|
45
|
+
chain: body.chain,
|
|
46
|
+
txHash: body.txHash,
|
|
47
|
+
includeSpam: "true"
|
|
48
|
+
});
|
|
49
|
+
const lookup = await fetch(`${processorUrl}/deposits?${query}`, { headers });
|
|
50
|
+
if (!lookup.ok) {
|
|
51
|
+
return jsonError("Could not verify the deposit", 502);
|
|
52
|
+
}
|
|
53
|
+
const { deposits = [] } = await lookup.json();
|
|
54
|
+
const owned = deposits.some(
|
|
55
|
+
(deposit) => deposit.depositAddress !== void 0 && deposit.token !== void 0 && sameIdentifier(deposit.depositAddress, body.account) && sameIdentifier(deposit.token, body.token)
|
|
56
|
+
);
|
|
57
|
+
if (!owned) {
|
|
58
|
+
return jsonError("Forbidden", 403);
|
|
59
|
+
}
|
|
60
|
+
const destination = _nullishCoalesce(authorization.refundDestination, () => ( body.destination));
|
|
61
|
+
const upstream = await fetch(`${processorUrl}/deposits/refund`, {
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers,
|
|
64
|
+
body: JSON.stringify({
|
|
65
|
+
chain: body.chain,
|
|
66
|
+
txHash: body.txHash,
|
|
67
|
+
account: body.account,
|
|
68
|
+
token: body.token,
|
|
69
|
+
recipient: destination
|
|
70
|
+
})
|
|
71
|
+
});
|
|
72
|
+
const text = await upstream.text();
|
|
73
|
+
if (!upstream.ok) {
|
|
74
|
+
return new Response(text, {
|
|
75
|
+
status: upstream.status,
|
|
76
|
+
headers: { "Content-Type": "application/json" }
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
let body_;
|
|
80
|
+
try {
|
|
81
|
+
body_ = JSON.parse(text);
|
|
82
|
+
} catch (e) {
|
|
83
|
+
return new Response(text, {
|
|
84
|
+
status: upstream.status,
|
|
85
|
+
headers: { "Content-Type": "application/json" }
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return new Response(
|
|
89
|
+
JSON.stringify({ ...body_, destination }),
|
|
90
|
+
{ status: upstream.status, headers: { "Content-Type": "application/json" } }
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
exports.createRefundHandler = createRefundHandler;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side helper for the claim flow. Import from
|
|
3
|
+
* `@rhinestone/deposit-modal/server` — this module talks to the processor with
|
|
4
|
+
* your API key and must never reach the browser.
|
|
5
|
+
*
|
|
6
|
+
* Deposit accounts are service-managed, so no user wallet can sign for a
|
|
7
|
+
* refund, and an exchange-funded deposit has no signable sender either.
|
|
8
|
+
* Whether a deposit belongs to a given user is something only your app knows,
|
|
9
|
+
* so that one decision is yours (`authorize`) and everything else is here.
|
|
10
|
+
*/
|
|
11
|
+
/** Body the ClaimModal POSTs to your endpoint. Never trusted on its own. */
|
|
12
|
+
interface RefundRequestBody {
|
|
13
|
+
chain: string;
|
|
14
|
+
txHash: string;
|
|
15
|
+
account: string;
|
|
16
|
+
token: string;
|
|
17
|
+
destination: string;
|
|
18
|
+
}
|
|
19
|
+
interface RefundAuthorization {
|
|
20
|
+
/**
|
|
21
|
+
* The deposit `recipient` this user owns — the same value your app passes
|
|
22
|
+
* `<DepositModal>`. Used *only* to prove the deposit belongs to them: the
|
|
23
|
+
* handler lists deposits settling to it and rejects a txHash that isn't
|
|
24
|
+
* among them.
|
|
25
|
+
*
|
|
26
|
+
* Not where the money goes. One recipient covers every deposit account the
|
|
27
|
+
* user has, since the account salt includes the target chain and token.
|
|
28
|
+
*/
|
|
29
|
+
depositRecipient: string;
|
|
30
|
+
/**
|
|
31
|
+
* Where the refund is paid. Set this to override whatever the browser asked
|
|
32
|
+
* for, taking the choice away from the page. Omit it to honour the address
|
|
33
|
+
* the user typed.
|
|
34
|
+
*/
|
|
35
|
+
refundDestination?: string;
|
|
36
|
+
}
|
|
37
|
+
interface CreateRefundHandlerOptions {
|
|
38
|
+
/** Write-scoped Rhinestone API key. Server-side only. */
|
|
39
|
+
apiKey: string;
|
|
40
|
+
/**
|
|
41
|
+
* Authenticate the caller and return the recipient they own, or `null` to
|
|
42
|
+
* reject with 401. This is the only part we can't write for you.
|
|
43
|
+
*/
|
|
44
|
+
authorize: (request: Request, refund: RefundRequestBody) => Promise<RefundAuthorization | null> | RefundAuthorization | null;
|
|
45
|
+
/** Defaults to the production processor. */
|
|
46
|
+
processorUrl?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Builds a `(Request) => Promise<Response>` you can mount in any fetch-based
|
|
50
|
+
* runtime (Next.js route handlers, Hono, Bun.serve, Cloudflare Workers).
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* // app/api/refund/route.ts
|
|
54
|
+
* export const POST = createRefundHandler({
|
|
55
|
+
* apiKey: process.env.RHINESTONE_API_KEY!,
|
|
56
|
+
* async authorize(request) {
|
|
57
|
+
* const session = await getSession(request);
|
|
58
|
+
* return session ? { depositRecipient: session.depositRecipient } : null;
|
|
59
|
+
* },
|
|
60
|
+
* });
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
declare function createRefundHandler(options: CreateRefundHandlerOptions): (request: Request) => Promise<Response>;
|
|
64
|
+
|
|
65
|
+
export { type CreateRefundHandlerOptions, type RefundAuthorization, createRefundHandler };
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side helper for the claim flow. Import from
|
|
3
|
+
* `@rhinestone/deposit-modal/server` — this module talks to the processor with
|
|
4
|
+
* your API key and must never reach the browser.
|
|
5
|
+
*
|
|
6
|
+
* Deposit accounts are service-managed, so no user wallet can sign for a
|
|
7
|
+
* refund, and an exchange-funded deposit has no signable sender either.
|
|
8
|
+
* Whether a deposit belongs to a given user is something only your app knows,
|
|
9
|
+
* so that one decision is yours (`authorize`) and everything else is here.
|
|
10
|
+
*/
|
|
11
|
+
/** Body the ClaimModal POSTs to your endpoint. Never trusted on its own. */
|
|
12
|
+
interface RefundRequestBody {
|
|
13
|
+
chain: string;
|
|
14
|
+
txHash: string;
|
|
15
|
+
account: string;
|
|
16
|
+
token: string;
|
|
17
|
+
destination: string;
|
|
18
|
+
}
|
|
19
|
+
interface RefundAuthorization {
|
|
20
|
+
/**
|
|
21
|
+
* The deposit `recipient` this user owns — the same value your app passes
|
|
22
|
+
* `<DepositModal>`. Used *only* to prove the deposit belongs to them: the
|
|
23
|
+
* handler lists deposits settling to it and rejects a txHash that isn't
|
|
24
|
+
* among them.
|
|
25
|
+
*
|
|
26
|
+
* Not where the money goes. One recipient covers every deposit account the
|
|
27
|
+
* user has, since the account salt includes the target chain and token.
|
|
28
|
+
*/
|
|
29
|
+
depositRecipient: string;
|
|
30
|
+
/**
|
|
31
|
+
* Where the refund is paid. Set this to override whatever the browser asked
|
|
32
|
+
* for, taking the choice away from the page. Omit it to honour the address
|
|
33
|
+
* the user typed.
|
|
34
|
+
*/
|
|
35
|
+
refundDestination?: string;
|
|
36
|
+
}
|
|
37
|
+
interface CreateRefundHandlerOptions {
|
|
38
|
+
/** Write-scoped Rhinestone API key. Server-side only. */
|
|
39
|
+
apiKey: string;
|
|
40
|
+
/**
|
|
41
|
+
* Authenticate the caller and return the recipient they own, or `null` to
|
|
42
|
+
* reject with 401. This is the only part we can't write for you.
|
|
43
|
+
*/
|
|
44
|
+
authorize: (request: Request, refund: RefundRequestBody) => Promise<RefundAuthorization | null> | RefundAuthorization | null;
|
|
45
|
+
/** Defaults to the production processor. */
|
|
46
|
+
processorUrl?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Builds a `(Request) => Promise<Response>` you can mount in any fetch-based
|
|
50
|
+
* runtime (Next.js route handlers, Hono, Bun.serve, Cloudflare Workers).
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* // app/api/refund/route.ts
|
|
54
|
+
* export const POST = createRefundHandler({
|
|
55
|
+
* apiKey: process.env.RHINESTONE_API_KEY!,
|
|
56
|
+
* async authorize(request) {
|
|
57
|
+
* const session = await getSession(request);
|
|
58
|
+
* return session ? { depositRecipient: session.depositRecipient } : null;
|
|
59
|
+
* },
|
|
60
|
+
* });
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
declare function createRefundHandler(options: CreateRefundHandlerOptions): (request: Request) => Promise<Response>;
|
|
64
|
+
|
|
65
|
+
export { type CreateRefundHandlerOptions, type RefundAuthorization, createRefundHandler };
|
package/dist/server.mjs
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// src/server.ts
|
|
2
|
+
var DEFAULT_PROCESSOR_URL = "https://v1.orchestrator.rhinestone.dev/deposit-processor";
|
|
3
|
+
function jsonError(message, status) {
|
|
4
|
+
return new Response(JSON.stringify({ error: message }), {
|
|
5
|
+
status,
|
|
6
|
+
headers: { "Content-Type": "application/json" }
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
function parseBody(value) {
|
|
10
|
+
if (typeof value !== "object" || value === null) return null;
|
|
11
|
+
const record = value;
|
|
12
|
+
const fields = ["chain", "txHash", "account", "token", "destination"];
|
|
13
|
+
for (const field of fields) {
|
|
14
|
+
if (typeof record[field] !== "string" || record[field] === "") return null;
|
|
15
|
+
}
|
|
16
|
+
return Object.fromEntries(
|
|
17
|
+
fields.map((field) => [field, record[field]])
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
function sameIdentifier(a, b) {
|
|
21
|
+
if (a === b) return true;
|
|
22
|
+
const isHex = (value) => /^0x[0-9a-fA-F]+$/.test(value);
|
|
23
|
+
return isHex(a) && isHex(b) && a.toLowerCase() === b.toLowerCase();
|
|
24
|
+
}
|
|
25
|
+
function createRefundHandler(options) {
|
|
26
|
+
const processorUrl = (options.processorUrl ?? DEFAULT_PROCESSOR_URL).replace(
|
|
27
|
+
/\/$/,
|
|
28
|
+
""
|
|
29
|
+
);
|
|
30
|
+
const headers = {
|
|
31
|
+
"Content-Type": "application/json",
|
|
32
|
+
"x-api-key": options.apiKey
|
|
33
|
+
};
|
|
34
|
+
return async function handleRefund(request) {
|
|
35
|
+
const body = parseBody(await request.json().catch(() => null));
|
|
36
|
+
if (!body) {
|
|
37
|
+
return jsonError("Malformed refund request", 400);
|
|
38
|
+
}
|
|
39
|
+
const authorization = await options.authorize(request, body);
|
|
40
|
+
if (!authorization) {
|
|
41
|
+
return jsonError("Unauthorized", 401);
|
|
42
|
+
}
|
|
43
|
+
const query = new URLSearchParams({
|
|
44
|
+
recipient: authorization.depositRecipient,
|
|
45
|
+
chain: body.chain,
|
|
46
|
+
txHash: body.txHash,
|
|
47
|
+
includeSpam: "true"
|
|
48
|
+
});
|
|
49
|
+
const lookup = await fetch(`${processorUrl}/deposits?${query}`, { headers });
|
|
50
|
+
if (!lookup.ok) {
|
|
51
|
+
return jsonError("Could not verify the deposit", 502);
|
|
52
|
+
}
|
|
53
|
+
const { deposits = [] } = await lookup.json();
|
|
54
|
+
const owned = deposits.some(
|
|
55
|
+
(deposit) => deposit.depositAddress !== void 0 && deposit.token !== void 0 && sameIdentifier(deposit.depositAddress, body.account) && sameIdentifier(deposit.token, body.token)
|
|
56
|
+
);
|
|
57
|
+
if (!owned) {
|
|
58
|
+
return jsonError("Forbidden", 403);
|
|
59
|
+
}
|
|
60
|
+
const destination = authorization.refundDestination ?? body.destination;
|
|
61
|
+
const upstream = await fetch(`${processorUrl}/deposits/refund`, {
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers,
|
|
64
|
+
body: JSON.stringify({
|
|
65
|
+
chain: body.chain,
|
|
66
|
+
txHash: body.txHash,
|
|
67
|
+
account: body.account,
|
|
68
|
+
token: body.token,
|
|
69
|
+
recipient: destination
|
|
70
|
+
})
|
|
71
|
+
});
|
|
72
|
+
const text = await upstream.text();
|
|
73
|
+
if (!upstream.ok) {
|
|
74
|
+
return new Response(text, {
|
|
75
|
+
status: upstream.status,
|
|
76
|
+
headers: { "Content-Type": "application/json" }
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
let body_;
|
|
80
|
+
try {
|
|
81
|
+
body_ = JSON.parse(text);
|
|
82
|
+
} catch {
|
|
83
|
+
return new Response(text, {
|
|
84
|
+
status: upstream.status,
|
|
85
|
+
headers: { "Content-Type": "application/json" }
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return new Response(
|
|
89
|
+
JSON.stringify({ ...body_, destination }),
|
|
90
|
+
{ status: upstream.status, headers: { "Content-Type": "application/json" } }
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
export {
|
|
95
|
+
createRefundHandler
|
|
96
|
+
};
|