@oasisprotocol/privana-sdk 0.3.0 → 0.4.1
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 +137 -17
- package/dist/chunk-CRJNDCDT.cjs +1773 -0
- package/dist/chunk-CRJNDCDT.cjs.map +1 -0
- package/dist/chunk-ZXFQJ5MG.js +1719 -0
- package/dist/chunk-ZXFQJ5MG.js.map +1 -0
- package/dist/index.cjs +326 -1728
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +68 -60
- package/dist/index.d.ts +68 -60
- package/dist/index.js +52 -1586
- package/dist/index.js.map +1 -1
- package/dist/on-ramp-DIAOtdeU.d.cts +115 -0
- package/dist/on-ramp-DIAOtdeU.d.ts +115 -0
- package/dist/on-ramp.cjs +958 -0
- package/dist/on-ramp.cjs.map +1 -0
- package/dist/on-ramp.d.cts +143 -0
- package/dist/on-ramp.d.ts +143 -0
- package/dist/on-ramp.js +955 -0
- package/dist/on-ramp.js.map +1 -0
- package/package.json +12 -1
package/dist/index.js
CHANGED
|
@@ -1,579 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import { WagmiContext, useAccount, useWalletClient, useConfig, useWriteContract, useSendTransaction, useChainId, useSwitchChain, useBalance as useBalance$1, useReadContract } from 'wagmi';
|
|
6
|
-
import { watchAccount, getAccount, getWalletClient } from 'wagmi/actions';
|
|
7
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { usePrivanaContext, createHostedAuthPendingStorageKey, clearHostedAuthPendingTransaction, HostedAuthRequiredError, HostedAuthError, createPkceVerifier, createPkceChallenge, createHostedAuthState, persistHostedAuthPendingTransaction, parseHostedAuthCallback, readHostedAuthPendingTransaction, HostedAuthStateMismatchError, buildHostedAuthSession, useSafePrivanaContext, usePrivateReadRequest, formatTokenAmount, useDepositVerification, getTransactionReceipt, waitForTransactionReceipt, cn, Button, stripHostedAuthCallbackParams, AccountingApiError, getChainId2, shortenAddress, formatTimeRemaining, parseTokenAmount, getExplorerAddressUrl } from './chunk-ZXFQJ5MG.js';
|
|
3
|
+
export { AccountingApiError, Button, HOSTED_AUTH_CLOCK_SKEW_MS, HostedAuthError, HostedAuthRequiredError, HostedAuthStateMismatchError, HttpClient, NETWORK_CONFIG, NetworkError, PrivanaClient, PrivanaProvider, SUPPORTED_CHAINS, SiweAuthProvider, Skeleton, ValidationError, applyRefreshResponse, buildHostedAuthSession, buttonVariants, clearHostedAuthPendingTransaction, createHostedAuthPendingStorageKey, createHostedAuthState, createHostedAuthStorageKey, createPkceChallenge, createPkceVerifier, getAccountingContract, getApiUrl, getChainById, getChainId, getExplorerAddressUrl, isHostedAuthRefreshActive, isHostedAuthSessionActive, normalizeAddress, normalizeHex, parseHostedAuthCallback, persistHostedAuthPendingTransaction, readHostedAuthPendingTransaction, readStoredHostedAuthSession, stripHostedAuthCallbackParams, syncHostedAuthSessionToClient, useDepositVerification, usePrivanaContext, useSafeAccount, useSafePrivanaContext, useSiweAuth } from './chunk-ZXFQJ5MG.js';
|
|
4
|
+
import { useState, useRef, useMemo, useCallback, useContext, useEffect, useId } from 'react';
|
|
8
5
|
import { QueryClientContext, useQuery, useQueryClient, useMutation, keepPreviousData } from '@tanstack/react-query';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { getTransactionReceipt as getTransactionReceipt$1, waitForTransactionReceipt as waitForTransactionReceipt$1, getTransaction, call } from 'viem/actions';
|
|
12
|
-
import { Slot } from '@radix-ui/react-slot';
|
|
13
|
-
import { cva } from 'class-variance-authority';
|
|
6
|
+
import { useAccount, useWalletClient, useConfig, useWriteContract, useSendTransaction, useChainId, useSwitchChain, useBalance as useBalance$1, useReadContract } from 'wagmi';
|
|
7
|
+
import { zeroAddress, erc20Abi } from 'viem';
|
|
14
8
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
15
9
|
import { XIcon } from 'lucide-react';
|
|
10
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
16
11
|
import { toast } from 'sonner';
|
|
17
12
|
|
|
18
|
-
// ../../shared/config.json
|
|
19
|
-
var config_default = {
|
|
20
|
-
chains: [
|
|
21
|
-
{
|
|
22
|
-
id: 84532,
|
|
23
|
-
name: "Base Sepolia",
|
|
24
|
-
explorerUrl: "https://sepolia.basescan.org"
|
|
25
|
-
}
|
|
26
|
-
],
|
|
27
|
-
networks: {
|
|
28
|
-
testnet: {
|
|
29
|
-
chainId: 23295,
|
|
30
|
-
name: "Sapphire Testnet",
|
|
31
|
-
accountingContract: "0xaF8e5de153A584528B57DD4B9B0195956BBDF571",
|
|
32
|
-
apiUrl: "https://testnet.privana.finance"
|
|
33
|
-
},
|
|
34
|
-
mainnet: {
|
|
35
|
-
chainId: 23294,
|
|
36
|
-
name: "Sapphire Mainnet",
|
|
37
|
-
accountingContract: "0x0000000000000000000000000000000000000000",
|
|
38
|
-
apiUrl: ""
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
// src/sdk/types/common.ts
|
|
44
|
-
var NETWORK_CONFIG = {
|
|
45
|
-
testnet: {
|
|
46
|
-
...config_default.networks.testnet,
|
|
47
|
-
accountingContract: config_default.networks.testnet.accountingContract
|
|
48
|
-
},
|
|
49
|
-
mainnet: {
|
|
50
|
-
...config_default.networks.mainnet,
|
|
51
|
-
accountingContract: config_default.networks.mainnet.accountingContract
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
function getChainId(network) {
|
|
55
|
-
return NETWORK_CONFIG[network].chainId;
|
|
56
|
-
}
|
|
57
|
-
function getAccountingContract(network) {
|
|
58
|
-
return NETWORK_CONFIG[network].accountingContract;
|
|
59
|
-
}
|
|
60
|
-
function getApiUrl(network) {
|
|
61
|
-
return NETWORK_CONFIG[network].apiUrl;
|
|
62
|
-
}
|
|
63
|
-
function normalizeHex(value) {
|
|
64
|
-
const normalized = value.trim().toLowerCase();
|
|
65
|
-
return normalized.startsWith("0x") ? normalized : `0x${normalized}`;
|
|
66
|
-
}
|
|
67
|
-
function normalizeAddress(value) {
|
|
68
|
-
return normalizeHex(value);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// src/sdk/types/chains.ts
|
|
72
|
-
var SUPPORTED_CHAINS = config_default.chains.map((chain) => ({
|
|
73
|
-
id: chain.id,
|
|
74
|
-
name: chain.name,
|
|
75
|
-
explorerUrl: chain.explorerUrl
|
|
76
|
-
}));
|
|
77
|
-
function getChainById(chainId) {
|
|
78
|
-
return SUPPORTED_CHAINS.find((c) => c.id === chainId);
|
|
79
|
-
}
|
|
80
|
-
function getExplorerAddressUrl(chainId, address) {
|
|
81
|
-
const chain = getChainById(chainId);
|
|
82
|
-
if (!chain) return void 0;
|
|
83
|
-
return `${chain.explorerUrl}/address/${address}#tokentxns`;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// src/sdk/auth/hosted-auth.ts
|
|
87
|
-
var HOSTED_AUTH_CLOCK_SKEW_MS = 3e4;
|
|
88
|
-
var PKCE_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
|
|
89
|
-
var DEFAULT_RANDOM_LENGTH = 64;
|
|
90
|
-
var HOSTED_AUTH_CALLBACK_QUERY_KEYS = ["code", "error", "error_description", "state"];
|
|
91
|
-
function randomString(length) {
|
|
92
|
-
const values = new Uint8Array(length);
|
|
93
|
-
crypto.getRandomValues(values);
|
|
94
|
-
let output = "";
|
|
95
|
-
for (const value of values) {
|
|
96
|
-
output += PKCE_CHARSET[value % PKCE_CHARSET.length];
|
|
97
|
-
}
|
|
98
|
-
return output;
|
|
99
|
-
}
|
|
100
|
-
function toBase64Url(bytes) {
|
|
101
|
-
let binary = "";
|
|
102
|
-
bytes.forEach((byte) => {
|
|
103
|
-
binary += String.fromCharCode(byte);
|
|
104
|
-
});
|
|
105
|
-
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
106
|
-
}
|
|
107
|
-
function createPkceVerifier(length = DEFAULT_RANDOM_LENGTH) {
|
|
108
|
-
return randomString(length);
|
|
109
|
-
}
|
|
110
|
-
async function createPkceChallenge(verifier) {
|
|
111
|
-
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
|
|
112
|
-
return toBase64Url(new Uint8Array(digest));
|
|
113
|
-
}
|
|
114
|
-
function createHostedAuthState(length = DEFAULT_RANDOM_LENGTH) {
|
|
115
|
-
return randomString(length);
|
|
116
|
-
}
|
|
117
|
-
function createHostedAuthStorageKey(apiUrl, config) {
|
|
118
|
-
const normalizedApiUrl = apiUrl.replace(/\/$/, "");
|
|
119
|
-
return [
|
|
120
|
-
"privana",
|
|
121
|
-
"hosted-auth",
|
|
122
|
-
normalizedApiUrl,
|
|
123
|
-
config.clientId.trim(),
|
|
124
|
-
config.redirectUri.trim()
|
|
125
|
-
].join(":");
|
|
126
|
-
}
|
|
127
|
-
function createHostedAuthPendingStorageKey(apiUrl, config) {
|
|
128
|
-
return `${createHostedAuthStorageKey(apiUrl, config)}:pending`;
|
|
129
|
-
}
|
|
130
|
-
function persistHostedAuthPendingTransaction(storage, key, transaction) {
|
|
131
|
-
storage.setItem(key, JSON.stringify(transaction));
|
|
132
|
-
}
|
|
133
|
-
function readHostedAuthPendingTransaction(storage, key) {
|
|
134
|
-
const raw = storage.getItem(key);
|
|
135
|
-
if (!raw) return null;
|
|
136
|
-
try {
|
|
137
|
-
const parsed = JSON.parse(raw);
|
|
138
|
-
if (typeof parsed.codeVerifier !== "string" || typeof parsed.state !== "string") {
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
return {
|
|
142
|
-
codeVerifier: parsed.codeVerifier,
|
|
143
|
-
state: parsed.state
|
|
144
|
-
};
|
|
145
|
-
} catch {
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
function clearHostedAuthPendingTransaction(storage, key) {
|
|
150
|
-
storage.removeItem(key);
|
|
151
|
-
}
|
|
152
|
-
function parseHostedAuthCallback(url, redirectUri) {
|
|
153
|
-
const expectedUrl = new URL(redirectUri);
|
|
154
|
-
if (url.origin !== expectedUrl.origin || url.pathname !== expectedUrl.pathname) {
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
157
|
-
const code = url.searchParams.get("code");
|
|
158
|
-
if (code) {
|
|
159
|
-
return {
|
|
160
|
-
code,
|
|
161
|
-
state: url.searchParams.get("state")
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
const error = url.searchParams.get("error");
|
|
165
|
-
if (error) {
|
|
166
|
-
return {
|
|
167
|
-
error,
|
|
168
|
-
errorDescription: url.searchParams.get("error_description") ?? void 0,
|
|
169
|
-
state: url.searchParams.get("state")
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
return null;
|
|
173
|
-
}
|
|
174
|
-
function stripHostedAuthCallbackParams(url) {
|
|
175
|
-
const nextUrl = new URL(url.toString());
|
|
176
|
-
HOSTED_AUTH_CALLBACK_QUERY_KEYS.forEach((key) => {
|
|
177
|
-
nextUrl.searchParams.delete(key);
|
|
178
|
-
});
|
|
179
|
-
return `${nextUrl.pathname}${nextUrl.search}${nextUrl.hash}`;
|
|
180
|
-
}
|
|
181
|
-
function buildHostedAuthSession(response, config, now = Date.now()) {
|
|
182
|
-
return {
|
|
183
|
-
accessToken: response.access_token,
|
|
184
|
-
refreshToken: response.refresh_token,
|
|
185
|
-
idToken: response.id_token,
|
|
186
|
-
tokenType: response.token_type,
|
|
187
|
-
address: response.address,
|
|
188
|
-
clientId: config.clientId,
|
|
189
|
-
redirectUri: config.redirectUri,
|
|
190
|
-
expiresAt: now + response.expires_in * 1e3,
|
|
191
|
-
refreshExpiresAt: now + response.refresh_expires_in * 1e3
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
function applyRefreshResponse(session, response, now = Date.now()) {
|
|
195
|
-
return {
|
|
196
|
-
...session,
|
|
197
|
-
accessToken: response.token,
|
|
198
|
-
refreshToken: response.refresh_token,
|
|
199
|
-
expiresAt: now + response.expires_in * 1e3,
|
|
200
|
-
refreshExpiresAt: now + response.refresh_expires_in * 1e3
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
function isHostedAuthSessionActive(session, now = Date.now(), skewMs = HOSTED_AUTH_CLOCK_SKEW_MS) {
|
|
204
|
-
return session.expiresAt > now + skewMs;
|
|
205
|
-
}
|
|
206
|
-
function isHostedAuthRefreshActive(session, now = Date.now(), skewMs = HOSTED_AUTH_CLOCK_SKEW_MS) {
|
|
207
|
-
return session.refreshExpiresAt > now + skewMs;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// src/sdk/client/errors.ts
|
|
211
|
-
var AccountingApiError = class _AccountingApiError extends Error {
|
|
212
|
-
constructor(message, statusCode, detail) {
|
|
213
|
-
super(message);
|
|
214
|
-
this.statusCode = statusCode;
|
|
215
|
-
this.detail = detail;
|
|
216
|
-
this.name = "AccountingApiError";
|
|
217
|
-
Object.setPrototypeOf(this, _AccountingApiError.prototype);
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
var NetworkError = class _NetworkError extends Error {
|
|
221
|
-
constructor(message, cause) {
|
|
222
|
-
super(message);
|
|
223
|
-
this.cause = cause;
|
|
224
|
-
this.name = "NetworkError";
|
|
225
|
-
Object.setPrototypeOf(this, _NetworkError.prototype);
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
var ValidationError = class _ValidationError extends Error {
|
|
229
|
-
constructor(message, field) {
|
|
230
|
-
super(message);
|
|
231
|
-
this.field = field;
|
|
232
|
-
this.name = "ValidationError";
|
|
233
|
-
Object.setPrototypeOf(this, _ValidationError.prototype);
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
var HostedAuthError = class _HostedAuthError extends Error {
|
|
237
|
-
constructor(message) {
|
|
238
|
-
super(message);
|
|
239
|
-
this.name = "HostedAuthError";
|
|
240
|
-
Object.setPrototypeOf(this, _HostedAuthError.prototype);
|
|
241
|
-
}
|
|
242
|
-
};
|
|
243
|
-
var HostedAuthRequiredError = class _HostedAuthRequiredError extends HostedAuthError {
|
|
244
|
-
constructor(message = "Hosted redirect authentication is required. Start login with useHostedRedirectAuth().") {
|
|
245
|
-
super(message);
|
|
246
|
-
this.name = "HostedAuthRequiredError";
|
|
247
|
-
Object.setPrototypeOf(this, _HostedAuthRequiredError.prototype);
|
|
248
|
-
}
|
|
249
|
-
};
|
|
250
|
-
var HostedAuthStateMismatchError = class _HostedAuthStateMismatchError extends HostedAuthError {
|
|
251
|
-
constructor(message = "Hosted authentication returned an invalid state value.") {
|
|
252
|
-
super(message);
|
|
253
|
-
this.name = "HostedAuthStateMismatchError";
|
|
254
|
-
Object.setPrototypeOf(this, _HostedAuthStateMismatchError.prototype);
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
// src/sdk/client/http-client.ts
|
|
259
|
-
var HttpClient = class {
|
|
260
|
-
constructor(config) {
|
|
261
|
-
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
262
|
-
this.timeout = config.timeout ?? 3e4;
|
|
263
|
-
this.headers = {
|
|
264
|
-
"Content-Type": "application/json",
|
|
265
|
-
...config.headers
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
async get(path) {
|
|
269
|
-
return this.request("GET", path);
|
|
270
|
-
}
|
|
271
|
-
async post(path, body) {
|
|
272
|
-
return this.request("POST", path, body);
|
|
273
|
-
}
|
|
274
|
-
getBaseUrl() {
|
|
275
|
-
return this.baseUrl;
|
|
276
|
-
}
|
|
277
|
-
setHeader(name, value) {
|
|
278
|
-
this.headers[name] = value;
|
|
279
|
-
}
|
|
280
|
-
removeHeader(name) {
|
|
281
|
-
delete this.headers[name];
|
|
282
|
-
}
|
|
283
|
-
getHeader(name) {
|
|
284
|
-
return this.headers[name];
|
|
285
|
-
}
|
|
286
|
-
async request(method, path, body) {
|
|
287
|
-
const url = `${this.baseUrl}${path}`;
|
|
288
|
-
const controller = new AbortController();
|
|
289
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
290
|
-
try {
|
|
291
|
-
const response = await fetch(url, {
|
|
292
|
-
method,
|
|
293
|
-
headers: this.headers,
|
|
294
|
-
body: body ? JSON.stringify(body) : void 0,
|
|
295
|
-
signal: controller.signal
|
|
296
|
-
});
|
|
297
|
-
clearTimeout(timeoutId);
|
|
298
|
-
if (!response.ok) {
|
|
299
|
-
let detail;
|
|
300
|
-
try {
|
|
301
|
-
const errorBody = await response.json();
|
|
302
|
-
detail = errorBody.detail || errorBody.error_description || errorBody.message;
|
|
303
|
-
} catch {
|
|
304
|
-
detail = await response.text().catch(() => void 0);
|
|
305
|
-
}
|
|
306
|
-
throw new AccountingApiError(
|
|
307
|
-
`API request failed: ${response.status} ${response.statusText}`,
|
|
308
|
-
response.status,
|
|
309
|
-
detail
|
|
310
|
-
);
|
|
311
|
-
}
|
|
312
|
-
return response.json();
|
|
313
|
-
} catch (error) {
|
|
314
|
-
clearTimeout(timeoutId);
|
|
315
|
-
if (error instanceof AccountingApiError) {
|
|
316
|
-
throw error;
|
|
317
|
-
}
|
|
318
|
-
if (error instanceof Error) {
|
|
319
|
-
if (error.name === "AbortError") {
|
|
320
|
-
throw new NetworkError(`Request timeout after ${this.timeout}ms`);
|
|
321
|
-
}
|
|
322
|
-
throw new NetworkError(`Network request failed: ${error.message}`, error);
|
|
323
|
-
}
|
|
324
|
-
throw new NetworkError("Unknown network error occurred");
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
// src/sdk/client/privana-client.ts
|
|
330
|
-
var PRIVATE_READ_TOKEN_HEADER = "X-SIWE-Token";
|
|
331
|
-
var MAX_BATCH_BALANCE_TOKEN_IDS = 100;
|
|
332
|
-
var MAX_HISTORY_PAGE_SIZE = 100;
|
|
333
|
-
var PrivanaClient = class {
|
|
334
|
-
constructor(config) {
|
|
335
|
-
this.http = new HttpClient(config);
|
|
336
|
-
}
|
|
337
|
-
getBaseUrl() {
|
|
338
|
-
return this.http.getBaseUrl();
|
|
339
|
-
}
|
|
340
|
-
async getDepositAddress(request = {}) {
|
|
341
|
-
return this.http.post("/v1/accounting/deposits/address", {
|
|
342
|
-
chain_type: request.chain_type ?? "evm",
|
|
343
|
-
version: request.version ?? 0
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
async checkDeposit(request) {
|
|
347
|
-
return this.http.post("/v1/accounting/deposits/check", {
|
|
348
|
-
chain_type: request.chain_type ?? "evm",
|
|
349
|
-
chain_id: request.chain_id,
|
|
350
|
-
tx_hash: normalizeHex(request.tx_hash),
|
|
351
|
-
amount: String(request.amount),
|
|
352
|
-
log_index: request.log_index ?? 0,
|
|
353
|
-
version: request.version ?? 0
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
async getDepositStatus(depositId) {
|
|
357
|
-
return this.http.get(`/v1/accounting/deposits/status/${depositId}`);
|
|
358
|
-
}
|
|
359
|
-
async getBalance(tokenId) {
|
|
360
|
-
const token = normalizeHex(tokenId);
|
|
361
|
-
return this.http.get(`/v1/accounting/balances/${token}`);
|
|
362
|
-
}
|
|
363
|
-
async getBatchBalances(request) {
|
|
364
|
-
if (request.token_ids.length > MAX_BATCH_BALANCE_TOKEN_IDS) {
|
|
365
|
-
throw new Error(
|
|
366
|
-
`Batch balance requests support at most ${MAX_BATCH_BALANCE_TOKEN_IDS} token IDs`
|
|
367
|
-
);
|
|
368
|
-
}
|
|
369
|
-
return this.http.post("/v1/accounting/balances/batch", {
|
|
370
|
-
token_ids: request.token_ids.map((id) => normalizeHex(id))
|
|
371
|
-
});
|
|
372
|
-
}
|
|
373
|
-
async getHistory(request = {}) {
|
|
374
|
-
const offset = request.offset ?? -1;
|
|
375
|
-
const limit = request.limit ?? 50;
|
|
376
|
-
if (!Number.isSafeInteger(offset)) {
|
|
377
|
-
throw new Error("History offset must be an integer");
|
|
378
|
-
}
|
|
379
|
-
if (!Number.isSafeInteger(limit)) {
|
|
380
|
-
throw new Error("History limit must be an integer");
|
|
381
|
-
}
|
|
382
|
-
if (limit < 0 || limit > MAX_HISTORY_PAGE_SIZE) {
|
|
383
|
-
throw new Error(`History requests support between 0 and ${MAX_HISTORY_PAGE_SIZE} entries`);
|
|
384
|
-
}
|
|
385
|
-
const params = new URLSearchParams({
|
|
386
|
-
offset: String(offset),
|
|
387
|
-
limit: String(limit)
|
|
388
|
-
});
|
|
389
|
-
return this.http.get(`/v1/accounting/history?${params.toString()}`);
|
|
390
|
-
}
|
|
391
|
-
async listTokens() {
|
|
392
|
-
return this.http.get("/v1/accounting/tokens");
|
|
393
|
-
}
|
|
394
|
-
async getTokenInfo(tokenId) {
|
|
395
|
-
const token = normalizeHex(tokenId);
|
|
396
|
-
return this.http.get(`/v1/accounting/tokens/${token}`);
|
|
397
|
-
}
|
|
398
|
-
async lockFunds(request) {
|
|
399
|
-
return this.http.post("/v1/accounting/funds/lock", {
|
|
400
|
-
service_address: normalizeAddress(request.service_address),
|
|
401
|
-
token_id: normalizeHex(request.token_id),
|
|
402
|
-
amount: String(request.amount),
|
|
403
|
-
expiry: String(request.expiry),
|
|
404
|
-
nonce: String(request.nonce),
|
|
405
|
-
signature: normalizeHex(request.signature)
|
|
406
|
-
});
|
|
407
|
-
}
|
|
408
|
-
async modifyLock(request) {
|
|
409
|
-
return this.http.post("/v1/accounting/funds/modify-lock", {
|
|
410
|
-
lock_id: request.lock_id,
|
|
411
|
-
amount: String(request.amount),
|
|
412
|
-
new_expiry: String(request.new_expiry),
|
|
413
|
-
nonce: String(request.nonce),
|
|
414
|
-
signature: normalizeHex(request.signature)
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
async unlockFunds(request) {
|
|
418
|
-
return this.http.post("/v1/accounting/funds/unlock", {
|
|
419
|
-
user_address: normalizeAddress(request.user_address),
|
|
420
|
-
lock_id: request.lock_id
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
async unlockAllExpired(request) {
|
|
424
|
-
return this.http.post(
|
|
425
|
-
"/v1/accounting/funds/unlock-all-expired",
|
|
426
|
-
{
|
|
427
|
-
user_address: normalizeAddress(request.user_address)
|
|
428
|
-
}
|
|
429
|
-
);
|
|
430
|
-
}
|
|
431
|
-
async getLockedFunds(serviceAddress) {
|
|
432
|
-
const queryParams = serviceAddress ? `?service_address=${normalizeAddress(serviceAddress)}` : "";
|
|
433
|
-
return this.http.get(`/v1/accounting/funds/locked${queryParams}`);
|
|
434
|
-
}
|
|
435
|
-
async getTotalLockedBalance(tokenId) {
|
|
436
|
-
const token = normalizeHex(tokenId);
|
|
437
|
-
return this.http.get(`/v1/accounting/funds/locked/total/${token}`);
|
|
438
|
-
}
|
|
439
|
-
async getExpiredLocks() {
|
|
440
|
-
return this.http.get("/v1/accounting/funds/expired");
|
|
441
|
-
}
|
|
442
|
-
async transferFunds(request) {
|
|
443
|
-
return this.http.post("/v1/accounting/funds/transfer", {
|
|
444
|
-
to_address: normalizeAddress(request.to_address),
|
|
445
|
-
token_id: normalizeHex(request.token_id),
|
|
446
|
-
amount: String(request.amount),
|
|
447
|
-
nonce: String(request.nonce),
|
|
448
|
-
signature: normalizeHex(request.signature)
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
|
-
async getTransferNonce(userAddress) {
|
|
452
|
-
const user = normalizeAddress(userAddress);
|
|
453
|
-
return this.http.get(`/v1/accounting/funds/transfer/nonce/${user}`);
|
|
454
|
-
}
|
|
455
|
-
async getLockNonce(userAddress) {
|
|
456
|
-
const user = normalizeAddress(userAddress);
|
|
457
|
-
return this.http.get(`/v1/accounting/funds/lock/nonce/${user}`);
|
|
458
|
-
}
|
|
459
|
-
async getModifyLockNonce(userAddress) {
|
|
460
|
-
const user = normalizeAddress(userAddress);
|
|
461
|
-
return this.http.get(`/v1/accounting/funds/modify-lock/nonce/${user}`);
|
|
462
|
-
}
|
|
463
|
-
async transferLockedFunds(request) {
|
|
464
|
-
return this.http.post("/v1/accounting/funds/transfer-locked", {
|
|
465
|
-
user_address: normalizeAddress(request.user_address),
|
|
466
|
-
lock_id: request.lock_id,
|
|
467
|
-
to_address: normalizeAddress(request.to_address),
|
|
468
|
-
amount: String(request.amount),
|
|
469
|
-
service_address: normalizeAddress(request.service_address),
|
|
470
|
-
nonce: String(request.nonce),
|
|
471
|
-
signature: normalizeHex(request.signature)
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
async withdrawFromLock(request) {
|
|
475
|
-
return this.http.post(
|
|
476
|
-
"/v1/accounting/funds/withdraw-from-lock",
|
|
477
|
-
{
|
|
478
|
-
to_address: normalizeAddress(request.to_address),
|
|
479
|
-
lock_id: request.lock_id,
|
|
480
|
-
amount: String(request.amount),
|
|
481
|
-
nonce: String(request.nonce),
|
|
482
|
-
signature: normalizeHex(request.signature)
|
|
483
|
-
}
|
|
484
|
-
);
|
|
485
|
-
}
|
|
486
|
-
async requestWithdrawal(request) {
|
|
487
|
-
return this.http.post("/v1/accounting/withdraw", {
|
|
488
|
-
token_id: normalizeHex(request.token_id),
|
|
489
|
-
amount: String(request.amount),
|
|
490
|
-
nonce: String(request.nonce),
|
|
491
|
-
signature: normalizeHex(request.signature)
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
|
-
async getWithdrawalNonce(userAddress) {
|
|
495
|
-
const user = normalizeAddress(userAddress);
|
|
496
|
-
return this.http.get(`/v1/accounting/withdraw/nonce/${user}`);
|
|
497
|
-
}
|
|
498
|
-
async getTransferLockedNonce(serviceAddress) {
|
|
499
|
-
const service = normalizeAddress(serviceAddress);
|
|
500
|
-
return this.http.get(
|
|
501
|
-
`/v1/accounting/funds/transfer-locked/nonce/${service}`
|
|
502
|
-
);
|
|
503
|
-
}
|
|
504
|
-
async getPendingWithdrawals(userAddress) {
|
|
505
|
-
const user = normalizeAddress(userAddress);
|
|
506
|
-
return this.http.get(`/v1/accounting/withdraw/pending/${user}`);
|
|
507
|
-
}
|
|
508
|
-
async getWithdrawalInfo(index) {
|
|
509
|
-
return this.http.get(`/v1/accounting/withdraw/${index}`);
|
|
510
|
-
}
|
|
511
|
-
async getSiweDomain() {
|
|
512
|
-
return this.http.get("/v1/accounting/auth/domain");
|
|
513
|
-
}
|
|
514
|
-
async getSiweNonce(userAddress) {
|
|
515
|
-
const user = normalizeAddress(userAddress);
|
|
516
|
-
return this.http.get(`/v1/accounting/auth/nonce?address=${user}`);
|
|
517
|
-
}
|
|
518
|
-
async loginWithSiwe(request) {
|
|
519
|
-
return this.http.post("/v1/accounting/auth/login", {
|
|
520
|
-
siwe_message: request.siwe_message,
|
|
521
|
-
signature: normalizeHex(request.signature)
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
getHostedAuthAuthorizeUrl(request) {
|
|
525
|
-
const url = new URL(
|
|
526
|
-
"v1/accounting/auth/authorize",
|
|
527
|
-
`${this.http.getBaseUrl().replace(/\/$/, "")}/`
|
|
528
|
-
);
|
|
529
|
-
url.searchParams.set("client_id", request.client_id);
|
|
530
|
-
url.searchParams.set("redirect_uri", request.redirect_uri);
|
|
531
|
-
url.searchParams.set("code_challenge", request.code_challenge);
|
|
532
|
-
url.searchParams.set("state", request.state);
|
|
533
|
-
url.searchParams.set("chain_id", String(request.chain_id));
|
|
534
|
-
url.searchParams.set("response_mode", request.response_mode ?? "redirect");
|
|
535
|
-
url.searchParams.set("code_challenge_method", request.code_challenge_method ?? "S256");
|
|
536
|
-
return url.toString();
|
|
537
|
-
}
|
|
538
|
-
async exchangeHostedAuthCode(request) {
|
|
539
|
-
return this.http.post("/v1/accounting/auth/token", {
|
|
540
|
-
grant_type: request.grant_type ?? "authorization_code",
|
|
541
|
-
code: request.code,
|
|
542
|
-
code_verifier: request.code_verifier,
|
|
543
|
-
client_id: request.client_id,
|
|
544
|
-
redirect_uri: request.redirect_uri
|
|
545
|
-
});
|
|
546
|
-
}
|
|
547
|
-
async refreshJwtSession(request) {
|
|
548
|
-
return this.http.post("/v1/accounting/auth/jwt/refresh", {
|
|
549
|
-
refresh_token: request.refresh_token
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
async logoutJwtSession(request = {}) {
|
|
553
|
-
return this.http.post("/v1/accounting/auth/jwt/logout", {
|
|
554
|
-
refresh_token: request.refresh_token,
|
|
555
|
-
revoke_all: request.revoke_all ?? false
|
|
556
|
-
});
|
|
557
|
-
}
|
|
558
|
-
setPrivateReadToken(token) {
|
|
559
|
-
this.http.removeHeader("Authorization");
|
|
560
|
-
this.http.setHeader(PRIVATE_READ_TOKEN_HEADER, token);
|
|
561
|
-
}
|
|
562
|
-
getPrivateReadToken() {
|
|
563
|
-
return this.http.getHeader(PRIVATE_READ_TOKEN_HEADER);
|
|
564
|
-
}
|
|
565
|
-
clearPrivateReadToken() {
|
|
566
|
-
this.http.removeHeader(PRIVATE_READ_TOKEN_HEADER);
|
|
567
|
-
}
|
|
568
|
-
setBearerToken(token) {
|
|
569
|
-
this.http.removeHeader(PRIVATE_READ_TOKEN_HEADER);
|
|
570
|
-
this.http.setHeader("Authorization", `Bearer ${token}`);
|
|
571
|
-
}
|
|
572
|
-
clearBearerToken() {
|
|
573
|
-
this.http.removeHeader("Authorization");
|
|
574
|
-
}
|
|
575
|
-
};
|
|
576
|
-
|
|
577
13
|
// src/sdk/signatures/eip712-types.ts
|
|
578
14
|
function createDomain(chainId, verifyingContract) {
|
|
579
15
|
return {
|
|
@@ -769,538 +205,6 @@ async function signWithdrawFromLockMessage({
|
|
|
769
205
|
});
|
|
770
206
|
return signature;
|
|
771
207
|
}
|
|
772
|
-
var defaultResult = {
|
|
773
|
-
address: void 0,
|
|
774
|
-
isConnected: false,
|
|
775
|
-
status: "disconnected"
|
|
776
|
-
};
|
|
777
|
-
function useSafeAccount() {
|
|
778
|
-
const context = useContext(WagmiContext);
|
|
779
|
-
const cacheRef = useRef(defaultResult);
|
|
780
|
-
const subscribe = useCallback(
|
|
781
|
-
(onChange) => {
|
|
782
|
-
if (!context) return () => {
|
|
783
|
-
};
|
|
784
|
-
return watchAccount(context, { onChange });
|
|
785
|
-
},
|
|
786
|
-
[context]
|
|
787
|
-
);
|
|
788
|
-
const getSnapshot = useCallback(() => {
|
|
789
|
-
if (!context) return defaultResult;
|
|
790
|
-
const account = getAccount(context);
|
|
791
|
-
if (cacheRef.current.address !== account.address || cacheRef.current.isConnected !== account.isConnected || cacheRef.current.status !== account.status) {
|
|
792
|
-
cacheRef.current = {
|
|
793
|
-
address: account.address,
|
|
794
|
-
isConnected: account.isConnected,
|
|
795
|
-
status: account.status
|
|
796
|
-
};
|
|
797
|
-
}
|
|
798
|
-
return cacheRef.current;
|
|
799
|
-
}, [context]);
|
|
800
|
-
const getServerSnapshot = useCallback(() => defaultResult, []);
|
|
801
|
-
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
// src/sdk/hooks/private-read-token-store.ts
|
|
805
|
-
var AUTH_CLOCK_SKEW_MS = 3e4;
|
|
806
|
-
var cache = /* @__PURE__ */ new Map();
|
|
807
|
-
function createScopeKey(apiUrl, chainId, address) {
|
|
808
|
-
return `${apiUrl.replace(/\/$/, "")}:${chainId}:${address.toLowerCase()}`;
|
|
809
|
-
}
|
|
810
|
-
function getCachedPrivateReadToken(scopeKey) {
|
|
811
|
-
const cached = cache.get(scopeKey);
|
|
812
|
-
if (!cached) return null;
|
|
813
|
-
if (cached.expiresAt <= Date.now() + AUTH_CLOCK_SKEW_MS) {
|
|
814
|
-
cache.delete(scopeKey);
|
|
815
|
-
return null;
|
|
816
|
-
}
|
|
817
|
-
return cached.token;
|
|
818
|
-
}
|
|
819
|
-
function setCachedPrivateReadToken(scopeKey, token, expiresAt) {
|
|
820
|
-
cache.set(scopeKey, { token, expiresAt });
|
|
821
|
-
}
|
|
822
|
-
function deleteCachedPrivateReadToken(scopeKey) {
|
|
823
|
-
cache.delete(scopeKey);
|
|
824
|
-
}
|
|
825
|
-
var DEFAULT_SIWE_VALIDITY_MS = 24 * 60 * 60 * 1e3;
|
|
826
|
-
var DEFAULT_STATEMENT = "Sign in to access your private account data.";
|
|
827
|
-
var AUTH_REFRESH_SKEW_MS = 3e4;
|
|
828
|
-
var SiweAuthContext = createContext(null);
|
|
829
|
-
function SiweAuthProvider({
|
|
830
|
-
children,
|
|
831
|
-
client,
|
|
832
|
-
networkConfig,
|
|
833
|
-
autoLogin = true,
|
|
834
|
-
statement
|
|
835
|
-
}) {
|
|
836
|
-
const wagmiContext = useContext(WagmiContext);
|
|
837
|
-
const { address, isConnected, status } = useSafeAccount();
|
|
838
|
-
const [session, setSession] = useState(null);
|
|
839
|
-
const [tokens, setTokens] = useState(null);
|
|
840
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
841
|
-
const [error, setError] = useState(null);
|
|
842
|
-
const [accessTokenExpiresAt, setAccessTokenExpiresAt] = useState(null);
|
|
843
|
-
const loginInFlight = useRef(false);
|
|
844
|
-
const autoAttemptedAddress = useRef(null);
|
|
845
|
-
const refreshInFlight = useRef(false);
|
|
846
|
-
const refreshDataRef = useRef(null);
|
|
847
|
-
const clearSession = useCallback(() => {
|
|
848
|
-
refreshDataRef.current = null;
|
|
849
|
-
setAccessTokenExpiresAt(null);
|
|
850
|
-
client.clearPrivateReadToken();
|
|
851
|
-
client.clearBearerToken();
|
|
852
|
-
setSession(null);
|
|
853
|
-
setTokens(null);
|
|
854
|
-
setError(null);
|
|
855
|
-
autoAttemptedAddress.current = null;
|
|
856
|
-
}, [client]);
|
|
857
|
-
const logout = useCallback(async () => {
|
|
858
|
-
setError(null);
|
|
859
|
-
const refreshToken = refreshDataRef.current?.refreshToken;
|
|
860
|
-
try {
|
|
861
|
-
if (refreshToken) {
|
|
862
|
-
await client.logoutJwtSession({ refresh_token: refreshToken });
|
|
863
|
-
}
|
|
864
|
-
} finally {
|
|
865
|
-
clearSession();
|
|
866
|
-
autoAttemptedAddress.current = address ?? null;
|
|
867
|
-
}
|
|
868
|
-
}, [clearSession, client, address]);
|
|
869
|
-
const login = useCallback(async () => {
|
|
870
|
-
if (!wagmiContext) throw new Error("WagmiProvider is required for SIWE auth");
|
|
871
|
-
if (!address) throw new Error("No wallet connected");
|
|
872
|
-
if (loginInFlight.current) return;
|
|
873
|
-
loginInFlight.current = true;
|
|
874
|
-
setIsLoading(true);
|
|
875
|
-
setError(null);
|
|
876
|
-
try {
|
|
877
|
-
const walletClient = await getWalletClient(wagmiContext);
|
|
878
|
-
if (!walletClient) throw new Error("No wallet client available");
|
|
879
|
-
const [{ domain }, nonceRes] = await Promise.all([
|
|
880
|
-
client.getSiweDomain(),
|
|
881
|
-
client.getSiweNonce(address)
|
|
882
|
-
]);
|
|
883
|
-
const issuedAt = /* @__PURE__ */ new Date();
|
|
884
|
-
const expirationTime = new Date(issuedAt.getTime() + DEFAULT_SIWE_VALIDITY_MS);
|
|
885
|
-
const uri = typeof window !== "undefined" && window.location.origin ? window.location.origin : networkConfig.apiUrl;
|
|
886
|
-
const message = createSiweMessage({
|
|
887
|
-
address,
|
|
888
|
-
chainId: networkConfig.chainId,
|
|
889
|
-
domain,
|
|
890
|
-
uri,
|
|
891
|
-
version: "1",
|
|
892
|
-
nonce: nonceRes.nonce,
|
|
893
|
-
statement: statement ?? DEFAULT_STATEMENT,
|
|
894
|
-
issuedAt,
|
|
895
|
-
expirationTime
|
|
896
|
-
});
|
|
897
|
-
const signature = await walletClient.signMessage({
|
|
898
|
-
account: walletClient.account ?? address,
|
|
899
|
-
message
|
|
900
|
-
});
|
|
901
|
-
const res = await client.loginWithSiwe({ siwe_message: message, signature });
|
|
902
|
-
const loggedInAt = Date.now();
|
|
903
|
-
client.setPrivateReadToken(res.siwe_token);
|
|
904
|
-
client.setBearerToken(res.jwt_access_token);
|
|
905
|
-
refreshDataRef.current = {
|
|
906
|
-
refreshToken: res.jwt_refresh_token,
|
|
907
|
-
refreshExpiresAt: loggedInAt + res.jwt_refresh_expires_in * 1e3
|
|
908
|
-
};
|
|
909
|
-
setCachedPrivateReadToken(
|
|
910
|
-
createScopeKey(networkConfig.apiUrl, networkConfig.chainId, address),
|
|
911
|
-
res.siwe_token,
|
|
912
|
-
expirationTime.getTime()
|
|
913
|
-
);
|
|
914
|
-
setSession({ address: res.address });
|
|
915
|
-
setTokens({
|
|
916
|
-
siwe_token: res.siwe_token,
|
|
917
|
-
jwt_access_token: res.jwt_access_token,
|
|
918
|
-
jwt_refresh_token: res.jwt_refresh_token,
|
|
919
|
-
address: res.address
|
|
920
|
-
});
|
|
921
|
-
setAccessTokenExpiresAt(loggedInAt + res.jwt_expires_in * 1e3);
|
|
922
|
-
} catch (err) {
|
|
923
|
-
setError(err instanceof Error ? err : new Error("Sign-in failed"));
|
|
924
|
-
throw err;
|
|
925
|
-
} finally {
|
|
926
|
-
setIsLoading(false);
|
|
927
|
-
loginInFlight.current = false;
|
|
928
|
-
}
|
|
929
|
-
}, [wagmiContext, address, client, networkConfig.chainId, networkConfig.apiUrl, statement]);
|
|
930
|
-
const refreshAccessToken = useCallback(async () => {
|
|
931
|
-
const data = refreshDataRef.current;
|
|
932
|
-
if (!data || refreshInFlight.current) return;
|
|
933
|
-
if (Date.now() >= data.refreshExpiresAt - AUTH_REFRESH_SKEW_MS) {
|
|
934
|
-
clearSession();
|
|
935
|
-
return;
|
|
936
|
-
}
|
|
937
|
-
refreshInFlight.current = true;
|
|
938
|
-
try {
|
|
939
|
-
const res = await client.refreshJwtSession({ refresh_token: data.refreshToken });
|
|
940
|
-
const refreshedAt = Date.now();
|
|
941
|
-
client.setBearerToken(res.token);
|
|
942
|
-
refreshDataRef.current = {
|
|
943
|
-
refreshToken: res.refresh_token,
|
|
944
|
-
refreshExpiresAt: refreshedAt + res.refresh_expires_in * 1e3
|
|
945
|
-
};
|
|
946
|
-
setTokens(
|
|
947
|
-
(prev) => prev ? { ...prev, jwt_access_token: res.token, jwt_refresh_token: res.refresh_token } : prev
|
|
948
|
-
);
|
|
949
|
-
setAccessTokenExpiresAt(refreshedAt + res.expires_in * 1e3);
|
|
950
|
-
} catch {
|
|
951
|
-
clearSession();
|
|
952
|
-
} finally {
|
|
953
|
-
refreshInFlight.current = false;
|
|
954
|
-
}
|
|
955
|
-
}, [client, clearSession]);
|
|
956
|
-
useEffect(() => {
|
|
957
|
-
if (accessTokenExpiresAt == null) return;
|
|
958
|
-
const delay = Math.max(accessTokenExpiresAt - AUTH_REFRESH_SKEW_MS - Date.now(), 0);
|
|
959
|
-
const timer = setTimeout(() => {
|
|
960
|
-
void refreshAccessToken();
|
|
961
|
-
}, delay);
|
|
962
|
-
return () => clearTimeout(timer);
|
|
963
|
-
}, [accessTokenExpiresAt, refreshAccessToken]);
|
|
964
|
-
useEffect(() => {
|
|
965
|
-
if (!autoLogin) return;
|
|
966
|
-
if (status === "connecting" || status === "reconnecting") return;
|
|
967
|
-
if (!isConnected && session) {
|
|
968
|
-
clearSession();
|
|
969
|
-
return;
|
|
970
|
-
}
|
|
971
|
-
if (isConnected && address && session && address.toLowerCase() !== session.address.toLowerCase()) {
|
|
972
|
-
clearSession();
|
|
973
|
-
return;
|
|
974
|
-
}
|
|
975
|
-
if (isConnected && address && !session && !isLoading && autoAttemptedAddress.current !== address) {
|
|
976
|
-
autoAttemptedAddress.current = address;
|
|
977
|
-
void login().catch(() => {
|
|
978
|
-
});
|
|
979
|
-
}
|
|
980
|
-
}, [autoLogin, status, isConnected, address, session, isLoading, login, clearSession]);
|
|
981
|
-
const value = useMemo(
|
|
982
|
-
() => ({
|
|
983
|
-
isAuthenticated: !!session,
|
|
984
|
-
isLoading,
|
|
985
|
-
error,
|
|
986
|
-
session,
|
|
987
|
-
accessToken: tokens?.jwt_access_token,
|
|
988
|
-
tokens,
|
|
989
|
-
login,
|
|
990
|
-
logout
|
|
991
|
-
}),
|
|
992
|
-
[session, isLoading, error, tokens, login, logout]
|
|
993
|
-
);
|
|
994
|
-
return /* @__PURE__ */ jsx(SiweAuthContext.Provider, { value, children });
|
|
995
|
-
}
|
|
996
|
-
function useSiweAuth() {
|
|
997
|
-
const ctx = useContext(SiweAuthContext);
|
|
998
|
-
if (!ctx) throw new Error("useSiweAuth must be used within SiweAuthProvider");
|
|
999
|
-
return ctx;
|
|
1000
|
-
}
|
|
1001
|
-
var PrivanaContext = createContext(null);
|
|
1002
|
-
function readStoredHostedAuthSession(storage, hostedAuthStorageKey, now = Date.now()) {
|
|
1003
|
-
const raw = storage.getItem(hostedAuthStorageKey);
|
|
1004
|
-
if (!raw) {
|
|
1005
|
-
return null;
|
|
1006
|
-
}
|
|
1007
|
-
try {
|
|
1008
|
-
const parsed = JSON.parse(raw);
|
|
1009
|
-
if (!isHostedAuthRefreshActive(parsed, now, 0)) {
|
|
1010
|
-
storage.removeItem(hostedAuthStorageKey);
|
|
1011
|
-
return null;
|
|
1012
|
-
}
|
|
1013
|
-
return parsed;
|
|
1014
|
-
} catch {
|
|
1015
|
-
storage.removeItem(hostedAuthStorageKey);
|
|
1016
|
-
return null;
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
function syncHostedAuthSessionToClient(client, hostedAuthConfig, hostedAuthSession) {
|
|
1020
|
-
if (!hostedAuthConfig) {
|
|
1021
|
-
client.clearBearerToken();
|
|
1022
|
-
client.clearPrivateReadToken();
|
|
1023
|
-
return;
|
|
1024
|
-
}
|
|
1025
|
-
if (hostedAuthSession && isHostedAuthSessionActive(hostedAuthSession)) {
|
|
1026
|
-
client.setBearerToken(hostedAuthSession.accessToken);
|
|
1027
|
-
client.clearPrivateReadToken();
|
|
1028
|
-
return;
|
|
1029
|
-
}
|
|
1030
|
-
client.clearBearerToken();
|
|
1031
|
-
client.clearPrivateReadToken();
|
|
1032
|
-
}
|
|
1033
|
-
var DEFAULT_NETWORK_CONFIG = NETWORK_CONFIG.testnet;
|
|
1034
|
-
function PrivanaProvider({
|
|
1035
|
-
children,
|
|
1036
|
-
networkConfig: networkConfigOverride,
|
|
1037
|
-
tokens,
|
|
1038
|
-
chains,
|
|
1039
|
-
pollingInterval = 1e4,
|
|
1040
|
-
serviceAddress,
|
|
1041
|
-
hostedAuth,
|
|
1042
|
-
siweAuth
|
|
1043
|
-
}) {
|
|
1044
|
-
if (hostedAuth && siweAuth) {
|
|
1045
|
-
throw new Error(
|
|
1046
|
-
"PrivanaProvider: `hostedAuth` and `siweAuth` are mutually exclusive - provide only one. When both are set, private reads use hosted auth and the in-app SIWE login is ignored."
|
|
1047
|
-
);
|
|
1048
|
-
}
|
|
1049
|
-
const networkConfig = useMemo(() => {
|
|
1050
|
-
const config = {
|
|
1051
|
-
...DEFAULT_NETWORK_CONFIG,
|
|
1052
|
-
...networkConfigOverride
|
|
1053
|
-
};
|
|
1054
|
-
if (!config.chainId || config.chainId <= 0) {
|
|
1055
|
-
throw new Error("PrivanaProvider: networkConfig.chainId must be a positive number");
|
|
1056
|
-
}
|
|
1057
|
-
if (!config.accountingContract || !config.accountingContract.startsWith("0x")) {
|
|
1058
|
-
throw new Error("PrivanaProvider: networkConfig.accountingContract must be a valid address");
|
|
1059
|
-
}
|
|
1060
|
-
if (!config.apiUrl) {
|
|
1061
|
-
throw new Error("PrivanaProvider: networkConfig.apiUrl must be provided");
|
|
1062
|
-
}
|
|
1063
|
-
return config;
|
|
1064
|
-
}, [
|
|
1065
|
-
networkConfigOverride?.chainId,
|
|
1066
|
-
networkConfigOverride?.name,
|
|
1067
|
-
networkConfigOverride?.accountingContract,
|
|
1068
|
-
networkConfigOverride?.apiUrl
|
|
1069
|
-
]);
|
|
1070
|
-
const resolvedChains = useMemo(() => {
|
|
1071
|
-
if (chains && chains.length > 0) return chains;
|
|
1072
|
-
return SUPPORTED_CHAINS;
|
|
1073
|
-
}, [chains]);
|
|
1074
|
-
const client = useMemo(
|
|
1075
|
-
() => new PrivanaClient({ baseUrl: networkConfig.apiUrl }),
|
|
1076
|
-
[networkConfig.apiUrl]
|
|
1077
|
-
);
|
|
1078
|
-
const [allTokens, setAllTokens] = useState([]);
|
|
1079
|
-
const [tokensStatus, setTokensStatus] = useState("loading");
|
|
1080
|
-
const [tokensError, setTokensError] = useState();
|
|
1081
|
-
useEffect(() => {
|
|
1082
|
-
setTokensStatus("loading");
|
|
1083
|
-
setTokensError(void 0);
|
|
1084
|
-
client.listTokens().then(({ tokens: list }) => {
|
|
1085
|
-
setAllTokens(
|
|
1086
|
-
list.map((t) => ({
|
|
1087
|
-
id: t.token_id,
|
|
1088
|
-
symbol: t.symbol,
|
|
1089
|
-
decimals: t.decimals,
|
|
1090
|
-
contract: t.token_address ?? zeroAddress,
|
|
1091
|
-
name: t.name,
|
|
1092
|
-
chainId: t.chain_id
|
|
1093
|
-
}))
|
|
1094
|
-
);
|
|
1095
|
-
setTokensStatus("ready");
|
|
1096
|
-
}).catch((err) => {
|
|
1097
|
-
setTokensError(err instanceof Error ? err : new Error(String(err)));
|
|
1098
|
-
setTokensStatus("error");
|
|
1099
|
-
});
|
|
1100
|
-
}, [client]);
|
|
1101
|
-
const enabledTokens = useMemo(() => {
|
|
1102
|
-
if (tokens && tokens.length > 0) {
|
|
1103
|
-
const allowed = new Set(tokens.map((id) => id.toLowerCase()));
|
|
1104
|
-
return allTokens.filter((t) => allowed.has(t.id.toLowerCase()));
|
|
1105
|
-
}
|
|
1106
|
-
return allTokens;
|
|
1107
|
-
}, [allTokens, tokens]);
|
|
1108
|
-
const tokenById = useMemo(
|
|
1109
|
-
() => Object.fromEntries(enabledTokens.map((t) => [t.id.toLowerCase(), t])),
|
|
1110
|
-
[enabledTokens]
|
|
1111
|
-
);
|
|
1112
|
-
const getTokenById = useMemo(() => (id) => tokenById[id.toLowerCase()], [tokenById]);
|
|
1113
|
-
const chainById = useMemo(
|
|
1114
|
-
() => Object.fromEntries(resolvedChains.map((c) => [c.id, c])),
|
|
1115
|
-
[resolvedChains]
|
|
1116
|
-
);
|
|
1117
|
-
const getChainById2 = useMemo(() => (id) => chainById[id], [chainById]);
|
|
1118
|
-
const hostedAuthConfig = useMemo(() => {
|
|
1119
|
-
if (!hostedAuth) return null;
|
|
1120
|
-
const clientId = hostedAuth.clientId.trim();
|
|
1121
|
-
const redirectUri = hostedAuth.redirectUri.trim();
|
|
1122
|
-
if (!clientId) {
|
|
1123
|
-
throw new Error(
|
|
1124
|
-
"PrivanaProvider: hostedAuth.clientId must be provided when hostedAuth is enabled"
|
|
1125
|
-
);
|
|
1126
|
-
}
|
|
1127
|
-
if (!redirectUri) {
|
|
1128
|
-
throw new Error(
|
|
1129
|
-
"PrivanaProvider: hostedAuth.redirectUri must be provided when hostedAuth is enabled"
|
|
1130
|
-
);
|
|
1131
|
-
}
|
|
1132
|
-
return {
|
|
1133
|
-
clientId,
|
|
1134
|
-
redirectUri
|
|
1135
|
-
};
|
|
1136
|
-
}, [hostedAuth]);
|
|
1137
|
-
const hostedAuthStorageKey = useMemo(
|
|
1138
|
-
() => hostedAuthConfig ? createHostedAuthStorageKey(networkConfig.apiUrl, hostedAuthConfig) : null,
|
|
1139
|
-
[hostedAuthConfig, networkConfig.apiUrl]
|
|
1140
|
-
);
|
|
1141
|
-
const [hostedAuthSession, setHostedAuthSessionState] = useState(null);
|
|
1142
|
-
const hostedAuthSessionRef = useRef(null);
|
|
1143
|
-
const hostedAuthStateVersionRef = useRef(0);
|
|
1144
|
-
const hostedAuthRefreshInflight = useRef(null);
|
|
1145
|
-
const clearHostedAuthSession = useCallback(() => {
|
|
1146
|
-
hostedAuthStateVersionRef.current += 1;
|
|
1147
|
-
hostedAuthSessionRef.current = null;
|
|
1148
|
-
hostedAuthRefreshInflight.current = null;
|
|
1149
|
-
setHostedAuthSessionState(null);
|
|
1150
|
-
client.clearBearerToken();
|
|
1151
|
-
client.clearPrivateReadToken();
|
|
1152
|
-
if (hostedAuthStorageKey && typeof window !== "undefined") {
|
|
1153
|
-
window.sessionStorage.removeItem(hostedAuthStorageKey);
|
|
1154
|
-
}
|
|
1155
|
-
}, [client, hostedAuthStorageKey]);
|
|
1156
|
-
const setHostedAuthSession = useCallback(
|
|
1157
|
-
(session) => {
|
|
1158
|
-
if (!session) {
|
|
1159
|
-
clearHostedAuthSession();
|
|
1160
|
-
return;
|
|
1161
|
-
}
|
|
1162
|
-
hostedAuthStateVersionRef.current += 1;
|
|
1163
|
-
hostedAuthSessionRef.current = session;
|
|
1164
|
-
setHostedAuthSessionState(session);
|
|
1165
|
-
if (isHostedAuthSessionActive(session)) {
|
|
1166
|
-
client.setBearerToken(session.accessToken);
|
|
1167
|
-
} else {
|
|
1168
|
-
client.clearBearerToken();
|
|
1169
|
-
}
|
|
1170
|
-
client.clearPrivateReadToken();
|
|
1171
|
-
if (hostedAuthStorageKey && typeof window !== "undefined") {
|
|
1172
|
-
window.sessionStorage.setItem(hostedAuthStorageKey, JSON.stringify(session));
|
|
1173
|
-
}
|
|
1174
|
-
},
|
|
1175
|
-
[clearHostedAuthSession, client, hostedAuthStorageKey]
|
|
1176
|
-
);
|
|
1177
|
-
const refreshHostedAuthSession = useCallback(async () => {
|
|
1178
|
-
if (!hostedAuthConfig) {
|
|
1179
|
-
throw new HostedAuthRequiredError(
|
|
1180
|
-
"Hosted redirect authentication is not configured for this provider."
|
|
1181
|
-
);
|
|
1182
|
-
}
|
|
1183
|
-
const currentSession = hostedAuthSessionRef.current;
|
|
1184
|
-
if (!currentSession) {
|
|
1185
|
-
throw new HostedAuthRequiredError();
|
|
1186
|
-
}
|
|
1187
|
-
if (!isHostedAuthRefreshActive(currentSession)) {
|
|
1188
|
-
clearHostedAuthSession();
|
|
1189
|
-
throw new HostedAuthRequiredError(
|
|
1190
|
-
"Hosted redirect authentication has expired. Start login again."
|
|
1191
|
-
);
|
|
1192
|
-
}
|
|
1193
|
-
if (hostedAuthRefreshInflight.current) {
|
|
1194
|
-
return hostedAuthRefreshInflight.current;
|
|
1195
|
-
}
|
|
1196
|
-
const refreshPromise = (async () => {
|
|
1197
|
-
const refreshVersion = hostedAuthStateVersionRef.current;
|
|
1198
|
-
try {
|
|
1199
|
-
const response = await client.refreshJwtSession({
|
|
1200
|
-
refresh_token: currentSession.refreshToken
|
|
1201
|
-
});
|
|
1202
|
-
if (refreshVersion !== hostedAuthStateVersionRef.current) {
|
|
1203
|
-
const latestSession = hostedAuthSessionRef.current;
|
|
1204
|
-
if (latestSession) {
|
|
1205
|
-
return latestSession;
|
|
1206
|
-
}
|
|
1207
|
-
throw new HostedAuthRequiredError(
|
|
1208
|
-
"Hosted redirect authentication has changed. Start login again."
|
|
1209
|
-
);
|
|
1210
|
-
}
|
|
1211
|
-
const nextSession = applyRefreshResponse(currentSession, response);
|
|
1212
|
-
setHostedAuthSession(nextSession);
|
|
1213
|
-
return nextSession;
|
|
1214
|
-
} catch (error) {
|
|
1215
|
-
if (refreshVersion === hostedAuthStateVersionRef.current) {
|
|
1216
|
-
clearHostedAuthSession();
|
|
1217
|
-
}
|
|
1218
|
-
throw error;
|
|
1219
|
-
} finally {
|
|
1220
|
-
hostedAuthRefreshInflight.current = null;
|
|
1221
|
-
}
|
|
1222
|
-
})();
|
|
1223
|
-
hostedAuthRefreshInflight.current = refreshPromise;
|
|
1224
|
-
return refreshPromise;
|
|
1225
|
-
}, [clearHostedAuthSession, client, hostedAuthConfig, setHostedAuthSession]);
|
|
1226
|
-
useEffect(() => {
|
|
1227
|
-
hostedAuthSessionRef.current = hostedAuthSession;
|
|
1228
|
-
}, [hostedAuthSession]);
|
|
1229
|
-
useEffect(() => {
|
|
1230
|
-
if (!hostedAuthStorageKey || typeof window === "undefined") {
|
|
1231
|
-
hostedAuthStateVersionRef.current += 1;
|
|
1232
|
-
hostedAuthSessionRef.current = null;
|
|
1233
|
-
hostedAuthRefreshInflight.current = null;
|
|
1234
|
-
setHostedAuthSessionState(null);
|
|
1235
|
-
return;
|
|
1236
|
-
}
|
|
1237
|
-
const restoredSession = readStoredHostedAuthSession(window.sessionStorage, hostedAuthStorageKey);
|
|
1238
|
-
hostedAuthStateVersionRef.current += 1;
|
|
1239
|
-
hostedAuthSessionRef.current = restoredSession;
|
|
1240
|
-
hostedAuthRefreshInflight.current = null;
|
|
1241
|
-
setHostedAuthSessionState(restoredSession);
|
|
1242
|
-
}, [hostedAuthStorageKey]);
|
|
1243
|
-
useEffect(() => {
|
|
1244
|
-
syncHostedAuthSessionToClient(client, hostedAuthConfig, hostedAuthSession);
|
|
1245
|
-
}, [client, hostedAuthConfig, hostedAuthSession]);
|
|
1246
|
-
const value = useMemo(
|
|
1247
|
-
() => ({
|
|
1248
|
-
client,
|
|
1249
|
-
networkConfig,
|
|
1250
|
-
enabledTokens,
|
|
1251
|
-
defaultToken: enabledTokens[0],
|
|
1252
|
-
getTokenById,
|
|
1253
|
-
getChainById: getChainById2,
|
|
1254
|
-
chains: resolvedChains,
|
|
1255
|
-
tokensStatus,
|
|
1256
|
-
tokensError,
|
|
1257
|
-
pollingInterval,
|
|
1258
|
-
serviceAddress,
|
|
1259
|
-
hostedAuthConfig,
|
|
1260
|
-
hostedAuthSession,
|
|
1261
|
-
setHostedAuthSession,
|
|
1262
|
-
clearHostedAuthSession,
|
|
1263
|
-
refreshHostedAuthSession
|
|
1264
|
-
}),
|
|
1265
|
-
[
|
|
1266
|
-
client,
|
|
1267
|
-
networkConfig,
|
|
1268
|
-
enabledTokens,
|
|
1269
|
-
getTokenById,
|
|
1270
|
-
getChainById2,
|
|
1271
|
-
resolvedChains,
|
|
1272
|
-
tokensStatus,
|
|
1273
|
-
tokensError,
|
|
1274
|
-
pollingInterval,
|
|
1275
|
-
serviceAddress,
|
|
1276
|
-
hostedAuthConfig,
|
|
1277
|
-
hostedAuthSession,
|
|
1278
|
-
setHostedAuthSession,
|
|
1279
|
-
clearHostedAuthSession,
|
|
1280
|
-
refreshHostedAuthSession
|
|
1281
|
-
]
|
|
1282
|
-
);
|
|
1283
|
-
return /* @__PURE__ */ jsx(PrivanaContext.Provider, { value, children: siweAuth ? /* @__PURE__ */ jsx(
|
|
1284
|
-
SiweAuthProvider,
|
|
1285
|
-
{
|
|
1286
|
-
client,
|
|
1287
|
-
networkConfig,
|
|
1288
|
-
autoLogin: siweAuth.autoLogin,
|
|
1289
|
-
statement: siweAuth.statement,
|
|
1290
|
-
children
|
|
1291
|
-
}
|
|
1292
|
-
) : children });
|
|
1293
|
-
}
|
|
1294
|
-
function usePrivanaContext() {
|
|
1295
|
-
const context = useContext(PrivanaContext);
|
|
1296
|
-
if (!context) {
|
|
1297
|
-
throw new Error("usePrivanaContext must be used within a PrivanaProvider");
|
|
1298
|
-
}
|
|
1299
|
-
return context;
|
|
1300
|
-
}
|
|
1301
|
-
function useSafePrivanaContext() {
|
|
1302
|
-
return useContext(PrivanaContext);
|
|
1303
|
-
}
|
|
1304
208
|
|
|
1305
209
|
// src/sdk/hooks/use-privana-client.ts
|
|
1306
210
|
function usePrivanaClient() {
|
|
@@ -1509,235 +413,6 @@ function useHostedRedirectAuth() {
|
|
|
1509
413
|
refresh
|
|
1510
414
|
};
|
|
1511
415
|
}
|
|
1512
|
-
function cn(...inputs) {
|
|
1513
|
-
return twMerge(clsx(inputs));
|
|
1514
|
-
}
|
|
1515
|
-
function formatTokenAmount(amount, decimals = 18) {
|
|
1516
|
-
const value = typeof amount === "string" ? BigInt(amount) : amount;
|
|
1517
|
-
const divisor = BigInt(10 ** decimals);
|
|
1518
|
-
const integerPart = value / divisor;
|
|
1519
|
-
const fractionalPart = value % divisor;
|
|
1520
|
-
const fractionalStr = fractionalPart.toString().padStart(decimals, "0");
|
|
1521
|
-
const twoDecimals = fractionalStr.slice(0, 2).padEnd(2, "0");
|
|
1522
|
-
const integerWithSpaces = integerPart.toString().replace(/\B(?=(\d{3})+(?!\d))/g, "\u2009");
|
|
1523
|
-
return `${integerWithSpaces}.${twoDecimals}`;
|
|
1524
|
-
}
|
|
1525
|
-
function parseTokenAmount(amount, decimals = 18) {
|
|
1526
|
-
const sanitized = amount.replace(/[\s\u2009]/g, "").replace(/,/g, ".");
|
|
1527
|
-
const lastDot = sanitized.lastIndexOf(".");
|
|
1528
|
-
const integerPart = lastDot === -1 ? sanitized : sanitized.slice(0, lastDot).replace(/\./g, "");
|
|
1529
|
-
const fractionalPart = lastDot === -1 ? "" : sanitized.slice(lastDot + 1);
|
|
1530
|
-
const paddedFractional = fractionalPart.padEnd(decimals, "0").slice(0, decimals);
|
|
1531
|
-
return BigInt(integerPart + paddedFractional);
|
|
1532
|
-
}
|
|
1533
|
-
function shortenAddress(address, chars = 4) {
|
|
1534
|
-
if (!address || address.length < chars * 2 + 2) return address;
|
|
1535
|
-
return `${address.slice(0, chars + 2)}...${address.slice(-chars)}`;
|
|
1536
|
-
}
|
|
1537
|
-
function formatTimeRemaining(expiryTimestamp) {
|
|
1538
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
1539
|
-
const diff = expiryTimestamp - now;
|
|
1540
|
-
if (diff <= 0) return "Expired";
|
|
1541
|
-
const days = Math.floor(diff / 86400);
|
|
1542
|
-
const hours = Math.floor(diff % 86400 / 3600);
|
|
1543
|
-
const minutes = Math.floor(diff % 3600 / 60);
|
|
1544
|
-
if (days > 0) {
|
|
1545
|
-
return hours > 0 ? `${days}d ${hours}h left` : `${days}d left`;
|
|
1546
|
-
}
|
|
1547
|
-
if (hours > 0) {
|
|
1548
|
-
return minutes > 0 ? `${hours}h ${minutes}m left` : `${hours}h left`;
|
|
1549
|
-
}
|
|
1550
|
-
return `${minutes}m left`;
|
|
1551
|
-
}
|
|
1552
|
-
var INITIAL_AUTH_BACKOFF_MS = 5e3;
|
|
1553
|
-
var MAX_AUTH_BACKOFF_MS = 6e4;
|
|
1554
|
-
var DEFAULT_SIWE_AUTH_VALIDITY_MS = 24 * 60 * 60 * 1e3;
|
|
1555
|
-
var PRIVATE_READ_STATEMENT = "Sign in to Privana to access private account data.";
|
|
1556
|
-
var privateReadFailureCache = /* @__PURE__ */ new Map();
|
|
1557
|
-
var privateReadInflight = /* @__PURE__ */ new Map();
|
|
1558
|
-
async function executeHostedAuthPrivateReadRequest({
|
|
1559
|
-
client,
|
|
1560
|
-
hostedAuthSession,
|
|
1561
|
-
refreshHostedAuthSession,
|
|
1562
|
-
request
|
|
1563
|
-
}) {
|
|
1564
|
-
const ensureHostedAuth = async (forceRefresh) => {
|
|
1565
|
-
if (!hostedAuthSession) {
|
|
1566
|
-
throw new HostedAuthRequiredError();
|
|
1567
|
-
}
|
|
1568
|
-
if (!forceRefresh && isHostedAuthSessionActive(hostedAuthSession)) {
|
|
1569
|
-
client.clearPrivateReadToken();
|
|
1570
|
-
client.setBearerToken(hostedAuthSession.accessToken);
|
|
1571
|
-
return hostedAuthSession.accessToken;
|
|
1572
|
-
}
|
|
1573
|
-
const refreshed = await refreshHostedAuthSession();
|
|
1574
|
-
client.clearPrivateReadToken();
|
|
1575
|
-
client.setBearerToken(refreshed.accessToken);
|
|
1576
|
-
return refreshed.accessToken;
|
|
1577
|
-
};
|
|
1578
|
-
await ensureHostedAuth(false);
|
|
1579
|
-
try {
|
|
1580
|
-
return await request();
|
|
1581
|
-
} catch (error) {
|
|
1582
|
-
if (!(error instanceof AccountingApiError) || error.statusCode !== 401) {
|
|
1583
|
-
throw error;
|
|
1584
|
-
}
|
|
1585
|
-
await ensureHostedAuth(true);
|
|
1586
|
-
return request();
|
|
1587
|
-
}
|
|
1588
|
-
}
|
|
1589
|
-
function clearPrivateReadScope(scopeKey, client) {
|
|
1590
|
-
deleteCachedPrivateReadToken(scopeKey);
|
|
1591
|
-
privateReadFailureCache.delete(scopeKey);
|
|
1592
|
-
client.clearPrivateReadToken();
|
|
1593
|
-
}
|
|
1594
|
-
function recordPrivateReadFailure(scopeKey) {
|
|
1595
|
-
const previous = privateReadFailureCache.get(scopeKey);
|
|
1596
|
-
const backoffMs = Math.min(
|
|
1597
|
-
previous ? previous.backoffMs * 2 : INITIAL_AUTH_BACKOFF_MS,
|
|
1598
|
-
MAX_AUTH_BACKOFF_MS
|
|
1599
|
-
);
|
|
1600
|
-
privateReadFailureCache.set(scopeKey, {
|
|
1601
|
-
backoffMs,
|
|
1602
|
-
retryAt: Date.now() + backoffMs
|
|
1603
|
-
});
|
|
1604
|
-
}
|
|
1605
|
-
function ensureFailureBackoff(scopeKey) {
|
|
1606
|
-
const failure = privateReadFailureCache.get(scopeKey);
|
|
1607
|
-
if (!failure) return;
|
|
1608
|
-
if (failure.retryAt <= Date.now()) {
|
|
1609
|
-
privateReadFailureCache.delete(scopeKey);
|
|
1610
|
-
return;
|
|
1611
|
-
}
|
|
1612
|
-
throw new Error(
|
|
1613
|
-
`Private-read authentication is temporarily paused after a recent failure. Retry in ${Math.ceil(
|
|
1614
|
-
(failure.retryAt - Date.now()) / 1e3
|
|
1615
|
-
)}s.`
|
|
1616
|
-
);
|
|
1617
|
-
}
|
|
1618
|
-
function usePrivateReadRequest() {
|
|
1619
|
-
const wagmiContext = useContext(WagmiContext);
|
|
1620
|
-
const { client, networkConfig, hostedAuthConfig, hostedAuthSession, refreshHostedAuthSession } = usePrivanaContext();
|
|
1621
|
-
const { address: walletAddress } = useSafeAccount();
|
|
1622
|
-
const privateReadAddress = hostedAuthConfig ? hostedAuthSession?.address ?? null : walletAddress ?? null;
|
|
1623
|
-
const privateReadReady = hostedAuthConfig ? !!hostedAuthSession : !!walletAddress;
|
|
1624
|
-
const executePrivateRead = useCallback(
|
|
1625
|
-
async (request) => {
|
|
1626
|
-
if (hostedAuthConfig) {
|
|
1627
|
-
return executeHostedAuthPrivateReadRequest({
|
|
1628
|
-
client,
|
|
1629
|
-
hostedAuthSession,
|
|
1630
|
-
refreshHostedAuthSession,
|
|
1631
|
-
request
|
|
1632
|
-
});
|
|
1633
|
-
}
|
|
1634
|
-
if (!wagmiContext) {
|
|
1635
|
-
throw new Error("WagmiProvider is required for authenticated private reads");
|
|
1636
|
-
}
|
|
1637
|
-
if (!walletAddress) {
|
|
1638
|
-
throw new Error("No wallet connected");
|
|
1639
|
-
}
|
|
1640
|
-
const walletClient = await getWalletClient(wagmiContext);
|
|
1641
|
-
if (!walletClient) {
|
|
1642
|
-
throw new Error("No wallet client available");
|
|
1643
|
-
}
|
|
1644
|
-
const apiUrl = networkConfig.apiUrl;
|
|
1645
|
-
const scopeKey = createScopeKey(apiUrl, networkConfig.chainId, walletAddress);
|
|
1646
|
-
const getToken = async (forceRefresh) => {
|
|
1647
|
-
const inflight = privateReadInflight.get(scopeKey);
|
|
1648
|
-
if (inflight) {
|
|
1649
|
-
const token = await inflight;
|
|
1650
|
-
client.setPrivateReadToken(token);
|
|
1651
|
-
return token;
|
|
1652
|
-
}
|
|
1653
|
-
if (!forceRefresh) {
|
|
1654
|
-
const cached = getCachedPrivateReadToken(scopeKey);
|
|
1655
|
-
if (cached) {
|
|
1656
|
-
client.setPrivateReadToken(cached);
|
|
1657
|
-
return cached;
|
|
1658
|
-
}
|
|
1659
|
-
}
|
|
1660
|
-
ensureFailureBackoff(scopeKey);
|
|
1661
|
-
const authPromise = (async () => {
|
|
1662
|
-
try {
|
|
1663
|
-
const [{ domain }, nonceResponse] = await Promise.all([
|
|
1664
|
-
client.getSiweDomain(),
|
|
1665
|
-
client.getSiweNonce(walletAddress)
|
|
1666
|
-
]);
|
|
1667
|
-
const issuedAt = /* @__PURE__ */ new Date();
|
|
1668
|
-
const expirationTime = new Date(issuedAt.getTime() + DEFAULT_SIWE_AUTH_VALIDITY_MS);
|
|
1669
|
-
const uri = typeof window !== "undefined" && window.location.origin ? window.location.origin : apiUrl;
|
|
1670
|
-
const message = createSiweMessage({
|
|
1671
|
-
address: walletAddress,
|
|
1672
|
-
chainId: walletClient.chain?.id ?? networkConfig.chainId,
|
|
1673
|
-
domain,
|
|
1674
|
-
expirationTime,
|
|
1675
|
-
issuedAt,
|
|
1676
|
-
nonce: nonceResponse.nonce,
|
|
1677
|
-
statement: PRIVATE_READ_STATEMENT,
|
|
1678
|
-
uri,
|
|
1679
|
-
version: "1"
|
|
1680
|
-
});
|
|
1681
|
-
const signature = await walletClient.signMessage({
|
|
1682
|
-
account: walletClient.account ?? walletAddress,
|
|
1683
|
-
message
|
|
1684
|
-
});
|
|
1685
|
-
const login = await client.loginWithSiwe({
|
|
1686
|
-
siwe_message: message,
|
|
1687
|
-
signature
|
|
1688
|
-
});
|
|
1689
|
-
setCachedPrivateReadToken(scopeKey, login.siwe_token, expirationTime.getTime());
|
|
1690
|
-
privateReadFailureCache.delete(scopeKey);
|
|
1691
|
-
client.setPrivateReadToken(login.siwe_token);
|
|
1692
|
-
return login.siwe_token;
|
|
1693
|
-
} catch (error) {
|
|
1694
|
-
const authError = error instanceof Error ? error : new Error("Failed to authenticate private reads");
|
|
1695
|
-
clearPrivateReadScope(scopeKey, client);
|
|
1696
|
-
recordPrivateReadFailure(scopeKey);
|
|
1697
|
-
throw authError;
|
|
1698
|
-
} finally {
|
|
1699
|
-
privateReadInflight.delete(scopeKey);
|
|
1700
|
-
}
|
|
1701
|
-
})();
|
|
1702
|
-
privateReadInflight.set(scopeKey, authPromise);
|
|
1703
|
-
return authPromise;
|
|
1704
|
-
};
|
|
1705
|
-
await getToken(false);
|
|
1706
|
-
try {
|
|
1707
|
-
return await request();
|
|
1708
|
-
} catch (error) {
|
|
1709
|
-
if (!(error instanceof AccountingApiError) || error.statusCode !== 401) {
|
|
1710
|
-
throw error;
|
|
1711
|
-
}
|
|
1712
|
-
clearPrivateReadScope(scopeKey, client);
|
|
1713
|
-
await getToken(true);
|
|
1714
|
-
return request();
|
|
1715
|
-
}
|
|
1716
|
-
},
|
|
1717
|
-
[
|
|
1718
|
-
client,
|
|
1719
|
-
hostedAuthConfig,
|
|
1720
|
-
hostedAuthSession,
|
|
1721
|
-
networkConfig.apiUrl,
|
|
1722
|
-
networkConfig.chainId,
|
|
1723
|
-
refreshHostedAuthSession,
|
|
1724
|
-
walletAddress,
|
|
1725
|
-
wagmiContext
|
|
1726
|
-
]
|
|
1727
|
-
);
|
|
1728
|
-
const privateReadQueryScope = useMemo(
|
|
1729
|
-
() => [networkConfig.apiUrl, networkConfig.chainId, privateReadAddress],
|
|
1730
|
-
[networkConfig.apiUrl, networkConfig.chainId, privateReadAddress]
|
|
1731
|
-
);
|
|
1732
|
-
return {
|
|
1733
|
-
executePrivateRead,
|
|
1734
|
-
privateReadAddress,
|
|
1735
|
-
privateReadReady,
|
|
1736
|
-
privateReadQueryScope
|
|
1737
|
-
};
|
|
1738
|
-
}
|
|
1739
|
-
|
|
1740
|
-
// src/sdk/hooks/use-balance.ts
|
|
1741
416
|
function useBalance(options = {}) {
|
|
1742
417
|
const queryClient = useContext(QueryClientContext);
|
|
1743
418
|
const accountingContext = useSafePrivanaContext();
|
|
@@ -1791,55 +466,6 @@ function useBatchBalances(options) {
|
|
|
1791
466
|
refetch: query.refetch
|
|
1792
467
|
};
|
|
1793
468
|
}
|
|
1794
|
-
|
|
1795
|
-
// ../../node_modules/@wagmi/core/dist/esm/utils/getAction.js
|
|
1796
|
-
function getAction(client, actionFn, name) {
|
|
1797
|
-
const action_implicit = client[actionFn.name];
|
|
1798
|
-
if (typeof action_implicit === "function")
|
|
1799
|
-
return action_implicit;
|
|
1800
|
-
const action_explicit = client[name];
|
|
1801
|
-
if (typeof action_explicit === "function")
|
|
1802
|
-
return action_explicit;
|
|
1803
|
-
return (params) => actionFn(client, params);
|
|
1804
|
-
}
|
|
1805
|
-
|
|
1806
|
-
// ../../node_modules/@wagmi/core/dist/esm/actions/getChainId.js
|
|
1807
|
-
function getChainId2(config) {
|
|
1808
|
-
return config.state.chainId;
|
|
1809
|
-
}
|
|
1810
|
-
async function getTransactionReceipt(config, parameters) {
|
|
1811
|
-
const { chainId, ...rest } = parameters;
|
|
1812
|
-
const client = config.getClient({ chainId });
|
|
1813
|
-
const action = getAction(client, getTransactionReceipt$1, "getTransactionReceipt");
|
|
1814
|
-
return action(rest);
|
|
1815
|
-
}
|
|
1816
|
-
async function waitForTransactionReceipt(config, parameters) {
|
|
1817
|
-
const { chainId, timeout = 0, ...rest } = parameters;
|
|
1818
|
-
const client = config.getClient({ chainId });
|
|
1819
|
-
const action = getAction(client, waitForTransactionReceipt$1, "waitForTransactionReceipt");
|
|
1820
|
-
const receipt = await action({ ...rest, timeout });
|
|
1821
|
-
if (receipt.status === "reverted") {
|
|
1822
|
-
const action_getTransaction = getAction(client, getTransaction, "getTransaction");
|
|
1823
|
-
const { from: account, ...txn } = await action_getTransaction({
|
|
1824
|
-
hash: receipt.transactionHash
|
|
1825
|
-
});
|
|
1826
|
-
const action_call = getAction(client, call, "call");
|
|
1827
|
-
const code = await action_call({
|
|
1828
|
-
...txn,
|
|
1829
|
-
account,
|
|
1830
|
-
data: txn.input,
|
|
1831
|
-
gasPrice: txn.type !== "eip1559" ? txn.gasPrice : void 0,
|
|
1832
|
-
maxFeePerGas: txn.type === "eip1559" ? txn.maxFeePerGas : void 0,
|
|
1833
|
-
maxPriorityFeePerGas: txn.type === "eip1559" ? txn.maxPriorityFeePerGas : void 0
|
|
1834
|
-
});
|
|
1835
|
-
const reason = code?.data ? hexToString(`0x${code.data.substring(138)}`) : "unknown reason";
|
|
1836
|
-
throw new Error(reason);
|
|
1837
|
-
}
|
|
1838
|
-
return {
|
|
1839
|
-
...receipt,
|
|
1840
|
-
chainId: client.chain.id
|
|
1841
|
-
};
|
|
1842
|
-
}
|
|
1843
469
|
function useEnsureCorrectChain() {
|
|
1844
470
|
const config = useConfig();
|
|
1845
471
|
const chainId = useChainId();
|
|
@@ -1930,19 +556,14 @@ function useDeposit(options = {}) {
|
|
|
1930
556
|
const queryClient = useQueryClient();
|
|
1931
557
|
const config = useConfig();
|
|
1932
558
|
const { executePrivateRead } = usePrivateReadRequest();
|
|
1933
|
-
const pollInterval = options.pollInterval ?? 5e3;
|
|
1934
|
-
const pollTimeout = options.pollTimeout ?? 18e4;
|
|
1935
559
|
const confirmations = options.confirmations ?? 15;
|
|
1936
560
|
const [depositAddress, setDepositAddress] = useState(null);
|
|
1937
561
|
const [txHash, setTxHash] = useState();
|
|
1938
562
|
const [isSwitchingChain, setIsSwitchingChain] = useState(false);
|
|
1939
563
|
const [isWaitingForConfirmation, setIsWaitingForConfirmation] = useState(false);
|
|
1940
|
-
const [
|
|
1941
|
-
const [didTimeout, setDidTimeout] = useState(false);
|
|
1942
|
-
const [verificationFailed, setVerificationFailed] = useState(false);
|
|
564
|
+
const [receiptFailed, setReceiptFailed] = useState(false);
|
|
1943
565
|
const [depositError, setDepositError] = useState(null);
|
|
1944
566
|
const generationRef = useRef(0);
|
|
1945
|
-
const pollIntervalRef = useRef(null);
|
|
1946
567
|
const verificationContextRef = useRef(null);
|
|
1947
568
|
const onDepositAddressReceivedRef = useRef(options.onDepositAddressReceived);
|
|
1948
569
|
const onDepositSuccessRef = useRef(options.onDepositSuccess);
|
|
@@ -1962,6 +583,28 @@ function useDeposit(options = {}) {
|
|
|
1962
583
|
options.onCheckTimeout,
|
|
1963
584
|
options.onError
|
|
1964
585
|
]);
|
|
586
|
+
const {
|
|
587
|
+
isVerifying,
|
|
588
|
+
didTimeout,
|
|
589
|
+
verificationFailed: innerVerificationFailed,
|
|
590
|
+
error: verificationError,
|
|
591
|
+
verify,
|
|
592
|
+
reset: resetVerification
|
|
593
|
+
} = useDepositVerification({
|
|
594
|
+
pollInterval: options.pollInterval,
|
|
595
|
+
pollTimeout: options.pollTimeout,
|
|
596
|
+
onCredited: (hash, response) => {
|
|
597
|
+
verificationContextRef.current = null;
|
|
598
|
+
if (address) clearPendingDeposit(address);
|
|
599
|
+
onCreditedRef.current?.(hash, response);
|
|
600
|
+
},
|
|
601
|
+
onCheckTimeout: (hash) => {
|
|
602
|
+
onCheckTimeoutRef.current?.(hash);
|
|
603
|
+
},
|
|
604
|
+
onError: (err) => {
|
|
605
|
+
onErrorRef.current?.(err);
|
|
606
|
+
}
|
|
607
|
+
});
|
|
1965
608
|
const addressMutation = useMutation({
|
|
1966
609
|
mutationFn: async () => {
|
|
1967
610
|
if (!address) throw new Error("No wallet connected");
|
|
@@ -1996,149 +639,24 @@ function useDeposit(options = {}) {
|
|
|
1996
639
|
useEffect(() => {
|
|
1997
640
|
return () => {
|
|
1998
641
|
invalidateGeneration();
|
|
1999
|
-
if (pollIntervalRef.current) {
|
|
2000
|
-
clearTimeout(pollIntervalRef.current);
|
|
2001
|
-
pollIntervalRef.current = null;
|
|
2002
|
-
}
|
|
2003
642
|
};
|
|
2004
643
|
}, [invalidateGeneration]);
|
|
2005
644
|
const resumedAddressRef = useRef(void 0);
|
|
2006
|
-
const stopPolling = useCallback(() => {
|
|
2007
|
-
if (pollIntervalRef.current) {
|
|
2008
|
-
clearTimeout(pollIntervalRef.current);
|
|
2009
|
-
pollIntervalRef.current = null;
|
|
2010
|
-
}
|
|
2011
|
-
}, []);
|
|
2012
645
|
const reset = useCallback(() => {
|
|
2013
646
|
generationRef.current++;
|
|
2014
|
-
|
|
647
|
+
resetVerification();
|
|
2015
648
|
if (address) clearPendingDeposit(address);
|
|
2016
649
|
verificationContextRef.current = null;
|
|
2017
650
|
setDepositAddress(null);
|
|
2018
651
|
setTxHash(void 0);
|
|
2019
652
|
setIsSwitchingChain(false);
|
|
2020
653
|
setIsWaitingForConfirmation(false);
|
|
2021
|
-
|
|
2022
|
-
setDidTimeout(false);
|
|
2023
|
-
setVerificationFailed(false);
|
|
654
|
+
setReceiptFailed(false);
|
|
2024
655
|
setDepositError(null);
|
|
2025
656
|
addressMutation.reset();
|
|
2026
657
|
resetWriteContract();
|
|
2027
658
|
resetSendTransaction();
|
|
2028
|
-
}, [address, addressMutation, resetWriteContract, resetSendTransaction,
|
|
2029
|
-
const runVerification = useCallback(
|
|
2030
|
-
async (ctx, generation) => {
|
|
2031
|
-
const isStale = () => generation !== generationRef.current;
|
|
2032
|
-
const { hash, chainId, amount } = ctx;
|
|
2033
|
-
setVerificationFailed(false);
|
|
2034
|
-
setDepositError(null);
|
|
2035
|
-
setDidTimeout(false);
|
|
2036
|
-
setIsWaitingForProcessing(true);
|
|
2037
|
-
const pollStartTime = Date.now();
|
|
2038
|
-
const markVerificationFailed = (err) => {
|
|
2039
|
-
setIsWaitingForProcessing(false);
|
|
2040
|
-
setDepositError(err);
|
|
2041
|
-
setVerificationFailed(true);
|
|
2042
|
-
onErrorRef.current?.(err);
|
|
2043
|
-
};
|
|
2044
|
-
try {
|
|
2045
|
-
const triggerResult = await executePrivateRead(
|
|
2046
|
-
() => client.checkDeposit({
|
|
2047
|
-
chain_id: chainId,
|
|
2048
|
-
tx_hash: hash,
|
|
2049
|
-
amount: amount.toString()
|
|
2050
|
-
})
|
|
2051
|
-
);
|
|
2052
|
-
if (isStale()) return;
|
|
2053
|
-
if (triggerResult.status === "credited") {
|
|
2054
|
-
setIsWaitingForProcessing(false);
|
|
2055
|
-
verificationContextRef.current = null;
|
|
2056
|
-
if (address) clearPendingDeposit(address);
|
|
2057
|
-
queryClient.invalidateQueries({ queryKey: ["accounting-balance"] });
|
|
2058
|
-
queryClient.invalidateQueries({ queryKey: ["accounting-history"] });
|
|
2059
|
-
onCreditedRef.current?.(hash, triggerResult);
|
|
2060
|
-
return;
|
|
2061
|
-
}
|
|
2062
|
-
if (triggerResult.status === "error") {
|
|
2063
|
-
markVerificationFailed(new Error(triggerResult.detail ?? "Deposit verification failed"));
|
|
2064
|
-
return;
|
|
2065
|
-
}
|
|
2066
|
-
const depositId = triggerResult.deposit_id;
|
|
2067
|
-
if (!depositId) {
|
|
2068
|
-
markVerificationFailed(new Error("Deposit check did not return a deposit id"));
|
|
2069
|
-
return;
|
|
2070
|
-
}
|
|
2071
|
-
let consecutiveFailures = 0;
|
|
2072
|
-
const checkStatus = async () => {
|
|
2073
|
-
if (isStale()) return true;
|
|
2074
|
-
if (Date.now() - pollStartTime > pollTimeout) {
|
|
2075
|
-
stopPolling();
|
|
2076
|
-
setIsWaitingForProcessing(false);
|
|
2077
|
-
setDidTimeout(true);
|
|
2078
|
-
onCheckTimeoutRef.current?.(hash);
|
|
2079
|
-
queryClient.invalidateQueries({ queryKey: ["accounting-balance"] });
|
|
2080
|
-
return true;
|
|
2081
|
-
}
|
|
2082
|
-
try {
|
|
2083
|
-
const result = await executePrivateRead(() => client.getDepositStatus(depositId));
|
|
2084
|
-
if (isStale()) return true;
|
|
2085
|
-
consecutiveFailures = 0;
|
|
2086
|
-
if (result.status === "credited") {
|
|
2087
|
-
stopPolling();
|
|
2088
|
-
setIsWaitingForProcessing(false);
|
|
2089
|
-
verificationContextRef.current = null;
|
|
2090
|
-
if (address) clearPendingDeposit(address);
|
|
2091
|
-
queryClient.invalidateQueries({ queryKey: ["accounting-balance"] });
|
|
2092
|
-
queryClient.invalidateQueries({ queryKey: ["accounting-history"] });
|
|
2093
|
-
onCreditedRef.current?.(hash, result);
|
|
2094
|
-
return true;
|
|
2095
|
-
}
|
|
2096
|
-
if (result.status === "error") {
|
|
2097
|
-
stopPolling();
|
|
2098
|
-
markVerificationFailed(new Error(result.detail ?? "Deposit verification failed"));
|
|
2099
|
-
return true;
|
|
2100
|
-
}
|
|
2101
|
-
} catch (err) {
|
|
2102
|
-
if (isStale()) return true;
|
|
2103
|
-
consecutiveFailures++;
|
|
2104
|
-
console.warn("Error polling deposit status:", err);
|
|
2105
|
-
if (consecutiveFailures >= 3) {
|
|
2106
|
-
stopPolling();
|
|
2107
|
-
markVerificationFailed(
|
|
2108
|
-
err instanceof Error ? err : new Error("Deposit status polling failed")
|
|
2109
|
-
);
|
|
2110
|
-
return true;
|
|
2111
|
-
}
|
|
2112
|
-
}
|
|
2113
|
-
return false;
|
|
2114
|
-
};
|
|
2115
|
-
const pollLoop = async () => {
|
|
2116
|
-
const done = await checkStatus();
|
|
2117
|
-
if (!done && !isStale() && pollIntervalRef.current !== null) {
|
|
2118
|
-
pollIntervalRef.current = setTimeout(pollLoop, pollInterval);
|
|
2119
|
-
}
|
|
2120
|
-
};
|
|
2121
|
-
pollIntervalRef.current = setTimeout(pollLoop, pollInterval);
|
|
2122
|
-
} catch (err) {
|
|
2123
|
-
if (isStale()) return;
|
|
2124
|
-
stopPolling();
|
|
2125
|
-
markVerificationFailed(
|
|
2126
|
-
err instanceof Error ? err : new Error("Deposit verification failed")
|
|
2127
|
-
);
|
|
2128
|
-
}
|
|
2129
|
-
},
|
|
2130
|
-
[address, client, executePrivateRead, pollInterval, pollTimeout, queryClient, stopPolling]
|
|
2131
|
-
);
|
|
2132
|
-
const retryVerification = useCallback(async () => {
|
|
2133
|
-
const ctx = verificationContextRef.current;
|
|
2134
|
-
if (!ctx) {
|
|
2135
|
-
throw new Error("No pending deposit to verify");
|
|
2136
|
-
}
|
|
2137
|
-
generationRef.current++;
|
|
2138
|
-
stopPolling();
|
|
2139
|
-
const generation = generationRef.current;
|
|
2140
|
-
await runVerification(ctx, generation);
|
|
2141
|
-
}, [runVerification, stopPolling]);
|
|
659
|
+
}, [address, addressMutation, resetWriteContract, resetSendTransaction, resetVerification]);
|
|
2142
660
|
useEffect(() => {
|
|
2143
661
|
if (!address || resumedAddressRef.current === address) return;
|
|
2144
662
|
const persisted = loadPendingDeposit(address);
|
|
@@ -2175,19 +693,17 @@ function useDeposit(options = {}) {
|
|
|
2175
693
|
setIsWaitingForConfirmation(false);
|
|
2176
694
|
onDepositSuccessRef.current?.(hash);
|
|
2177
695
|
queryClient.invalidateQueries({ queryKey: ["readContract"] });
|
|
2178
|
-
await
|
|
696
|
+
await verify(ctx);
|
|
2179
697
|
} catch (err) {
|
|
2180
698
|
if (isStale()) return;
|
|
2181
699
|
setIsWaitingForConfirmation(false);
|
|
2182
|
-
stopPolling();
|
|
2183
700
|
const error2 = err instanceof Error ? err : new Error("Deposit verification failed");
|
|
2184
|
-
setIsWaitingForProcessing(false);
|
|
2185
701
|
setDepositError(error2);
|
|
2186
|
-
|
|
702
|
+
setReceiptFailed(true);
|
|
2187
703
|
onErrorRef.current?.(error2);
|
|
2188
704
|
}
|
|
2189
705
|
})();
|
|
2190
|
-
}, [address, config, confirmations, queryClient,
|
|
706
|
+
}, [address, config, confirmations, queryClient, verify]);
|
|
2191
707
|
const deposit = useCallback(
|
|
2192
708
|
async (params) => {
|
|
2193
709
|
if (verificationContextRef.current) {
|
|
@@ -2265,15 +781,13 @@ function useDeposit(options = {}) {
|
|
|
2265
781
|
if (isStale()) return;
|
|
2266
782
|
onDepositSuccessRef.current?.(hash);
|
|
2267
783
|
queryClient.invalidateQueries({ queryKey: ["readContract"] });
|
|
2268
|
-
await
|
|
784
|
+
await verify(ctx);
|
|
2269
785
|
} catch (err) {
|
|
2270
786
|
if (isStale()) return;
|
|
2271
787
|
setIsWaitingForConfirmation(false);
|
|
2272
|
-
stopPolling();
|
|
2273
788
|
const error2 = err instanceof Error ? err : new Error("Deposit verification failed");
|
|
2274
|
-
setIsWaitingForProcessing(false);
|
|
2275
789
|
setDepositError(error2);
|
|
2276
|
-
|
|
790
|
+
setReceiptFailed(true);
|
|
2277
791
|
onErrorRef.current?.(error2);
|
|
2278
792
|
}
|
|
2279
793
|
} catch (err) {
|
|
@@ -2295,13 +809,21 @@ function useDeposit(options = {}) {
|
|
|
2295
809
|
queryClient,
|
|
2296
810
|
writeContractAsync,
|
|
2297
811
|
sendTransactionAsync,
|
|
2298
|
-
stopPolling,
|
|
2299
812
|
reset,
|
|
2300
|
-
|
|
813
|
+
verify
|
|
2301
814
|
]
|
|
2302
815
|
);
|
|
2303
|
-
const
|
|
2304
|
-
|
|
816
|
+
const retryVerification = useCallback(async () => {
|
|
817
|
+
const ctx = verificationContextRef.current;
|
|
818
|
+
if (!ctx) {
|
|
819
|
+
throw new Error("No pending deposit to verify");
|
|
820
|
+
}
|
|
821
|
+
setReceiptFailed(false);
|
|
822
|
+
setDepositError(null);
|
|
823
|
+
await verify(ctx);
|
|
824
|
+
}, [verify]);
|
|
825
|
+
const isPending = addressMutation.isPending || isSwitchingChain || isSendingTx || isWaitingForConfirmation || isVerifying;
|
|
826
|
+
const error = addressMutation.error || sendError || depositError || verificationError;
|
|
2305
827
|
return {
|
|
2306
828
|
depositAddress,
|
|
2307
829
|
txHash,
|
|
@@ -2309,9 +831,9 @@ function useDeposit(options = {}) {
|
|
|
2309
831
|
isSwitchingChain,
|
|
2310
832
|
isSendingTransaction: isSendingTx,
|
|
2311
833
|
isWaitingForConfirmation,
|
|
2312
|
-
isWaitingForProcessing,
|
|
834
|
+
isWaitingForProcessing: isVerifying,
|
|
2313
835
|
didTimeout,
|
|
2314
|
-
verificationFailed,
|
|
836
|
+
verificationFailed: innerVerificationFailed || receiptFailed,
|
|
2315
837
|
isPending,
|
|
2316
838
|
error,
|
|
2317
839
|
deposit,
|
|
@@ -2971,52 +1493,6 @@ function useModifyLock(options = {}) {
|
|
|
2971
1493
|
reset: mutation.reset
|
|
2972
1494
|
};
|
|
2973
1495
|
}
|
|
2974
|
-
var buttonVariants = cva(
|
|
2975
|
-
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
2976
|
-
{
|
|
2977
|
-
variants: {
|
|
2978
|
-
variant: {
|
|
2979
|
-
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
2980
|
-
destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
2981
|
-
outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
|
2982
|
-
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
2983
|
-
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
2984
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
2985
|
-
},
|
|
2986
|
-
size: {
|
|
2987
|
-
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
2988
|
-
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
2989
|
-
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
2990
|
-
icon: "size-9",
|
|
2991
|
-
"icon-sm": "size-8",
|
|
2992
|
-
"icon-lg": "size-10"
|
|
2993
|
-
}
|
|
2994
|
-
},
|
|
2995
|
-
defaultVariants: {
|
|
2996
|
-
variant: "default",
|
|
2997
|
-
size: "default"
|
|
2998
|
-
}
|
|
2999
|
-
}
|
|
3000
|
-
);
|
|
3001
|
-
function Button({
|
|
3002
|
-
className,
|
|
3003
|
-
variant = "default",
|
|
3004
|
-
size = "default",
|
|
3005
|
-
asChild = false,
|
|
3006
|
-
...props
|
|
3007
|
-
}) {
|
|
3008
|
-
const Comp = asChild ? Slot : "button";
|
|
3009
|
-
return /* @__PURE__ */ jsx(
|
|
3010
|
-
Comp,
|
|
3011
|
-
{
|
|
3012
|
-
"data-slot": "button",
|
|
3013
|
-
"data-variant": variant,
|
|
3014
|
-
"data-size": size,
|
|
3015
|
-
className: cn(buttonVariants({ variant, size, className })),
|
|
3016
|
-
...props
|
|
3017
|
-
}
|
|
3018
|
-
);
|
|
3019
|
-
}
|
|
3020
1496
|
function Dialog({ ...props }) {
|
|
3021
1497
|
return /* @__PURE__ */ jsx(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
3022
1498
|
}
|
|
@@ -4625,17 +3101,7 @@ function PrivanaButton({
|
|
|
4625
3101
|
)
|
|
4626
3102
|
] });
|
|
4627
3103
|
}
|
|
4628
|
-
function Skeleton({ className, ...props }) {
|
|
4629
|
-
return /* @__PURE__ */ jsx(
|
|
4630
|
-
"div",
|
|
4631
|
-
{
|
|
4632
|
-
"data-slot": "skeleton",
|
|
4633
|
-
className: cn("bg-accent animate-pulse rounded-md", className),
|
|
4634
|
-
...props
|
|
4635
|
-
}
|
|
4636
|
-
);
|
|
4637
|
-
}
|
|
4638
3104
|
|
|
4639
|
-
export {
|
|
3105
|
+
export { LOCK_TYPES, MODIFY_LOCK_TYPES, PrivanaButton, PrivanaInlineModal, PrivanaModal, TRANSFER_LOCKED_TYPES, TRANSFER_TYPES, WITHDRAW_FROM_LOCK_TYPES, WITHDRAW_TYPES, createDomain, createLockExpiry, getChainIcon, getTokenIcon, signLockMessage, signModifyLockMessage, signTransferLockedMessage, signTransferMessage, signWithdrawFromLockMessage, signWithdrawMessage, useBalance, useBatchBalances, useDeposit, useExpiredLocks, useHistory, useHostedRedirectAuth, useLockFunds, useLockedFunds, useModifyLock, usePendingWithdrawals, usePrivanaClient, useTokenInfo, useTokenList, useTotalLockedBalance, useTransfer, useUnlockFunds, useWithdraw };
|
|
4640
3106
|
//# sourceMappingURL=index.js.map
|
|
4641
3107
|
//# sourceMappingURL=index.js.map
|