@pooflabs/web 0.0.62 → 0.0.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/providers/privy-wallet-provider.d.ts +6 -0
- package/dist/{index-BCpgjKea.js → index-9kQbe-Gv.js} +291 -40
- package/dist/{index-7_nqSSXr.esm.js.map → index-9kQbe-Gv.js.map} +1 -1
- package/dist/{index-C2cjjAWD.js → index-BmJDdk1y.js} +2 -2
- package/dist/{index-C2cjjAWD.js.map → index-BmJDdk1y.js.map} +1 -1
- package/dist/{index-7_nqSSXr.esm.js → index-BoT2Jvpf.esm.js} +290 -41
- package/dist/index-BoT2Jvpf.esm.js.map +1 -0
- package/dist/{index-B4o54izZ.esm.js → index-Dd2ogXqG.esm.js} +2 -2
- package/dist/{index-B4o54izZ.esm.js.map → index-Dd2ogXqG.esm.js.map} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/index-BCpgjKea.js.map +0 -1
|
@@ -70,5 +70,11 @@ export declare class PrivyWalletProvider implements AuthProvider {
|
|
|
70
70
|
signMessage(message: string): Promise<string>;
|
|
71
71
|
restoreSession(): Promise<User | null>;
|
|
72
72
|
private createSession;
|
|
73
|
+
/**
|
|
74
|
+
* Waits for a wallet matching the session address to appear in the wallets array.
|
|
75
|
+
* This handles the timing gap where Privy's embedded wallet (created for email login users)
|
|
76
|
+
* may not yet be in the useWallets() array when signTransaction is called immediately after login.
|
|
77
|
+
*/
|
|
78
|
+
private waitForMatchingWallet;
|
|
73
79
|
private ensureReady;
|
|
74
80
|
}
|
|
@@ -6541,10 +6541,14 @@ class WebSessionManager {
|
|
|
6541
6541
|
const newObj = JSON.parse(newSession);
|
|
6542
6542
|
return { address: newObj.address, session: newObj };
|
|
6543
6543
|
}
|
|
6544
|
+
// Refresh failed — clear stale session to prevent retry loops
|
|
6545
|
+
this.clearSession();
|
|
6544
6546
|
return null;
|
|
6545
6547
|
}
|
|
6546
6548
|
}
|
|
6547
6549
|
catch (err) {
|
|
6550
|
+
// Token decode or refresh failed — clear stale session to prevent retry loops
|
|
6551
|
+
this.clearSession();
|
|
6548
6552
|
return null;
|
|
6549
6553
|
}
|
|
6550
6554
|
return { address: sessionObj.address, session: sessionObj };
|
|
@@ -9468,15 +9472,30 @@ class ServerSessionManager {
|
|
|
9468
9472
|
constructor() {
|
|
9469
9473
|
/* Private cache (lives for the life of the process) */
|
|
9470
9474
|
this.session = null;
|
|
9475
|
+
/* Coalesce concurrent getSession() calls into a single in-flight request */
|
|
9476
|
+
this.pendingSession = null;
|
|
9471
9477
|
}
|
|
9472
9478
|
/* ---------------------------------------------- *
|
|
9473
9479
|
* GET (lazy-fetch)
|
|
9474
9480
|
* ---------------------------------------------- */
|
|
9475
9481
|
async getSession() {
|
|
9476
|
-
if (this.session
|
|
9477
|
-
this.session
|
|
9478
|
-
}
|
|
9479
|
-
|
|
9482
|
+
if (this.session !== null) {
|
|
9483
|
+
return this.session;
|
|
9484
|
+
}
|
|
9485
|
+
// If a session creation is already in-flight, reuse that promise
|
|
9486
|
+
// instead of firing a second concurrent request.
|
|
9487
|
+
if (this.pendingSession !== null) {
|
|
9488
|
+
return this.pendingSession;
|
|
9489
|
+
}
|
|
9490
|
+
this.pendingSession = createSession()
|
|
9491
|
+
.then((session) => {
|
|
9492
|
+
this.session = session;
|
|
9493
|
+
return session;
|
|
9494
|
+
})
|
|
9495
|
+
.finally(() => {
|
|
9496
|
+
this.pendingSession = null;
|
|
9497
|
+
});
|
|
9498
|
+
return this.pendingSession;
|
|
9480
9499
|
}
|
|
9481
9500
|
/* ---------------------------------------------- *
|
|
9482
9501
|
* STORE (overwrites the cached value)
|
|
@@ -9489,6 +9508,7 @@ class ServerSessionManager {
|
|
|
9489
9508
|
* ---------------------------------------------- */
|
|
9490
9509
|
clearSession() {
|
|
9491
9510
|
this.session = null;
|
|
9511
|
+
this.pendingSession = null;
|
|
9492
9512
|
}
|
|
9493
9513
|
/* ---------------------------------------------- *
|
|
9494
9514
|
* QUICK helpers
|
|
@@ -9791,6 +9811,150 @@ function hashForKey$1(value) {
|
|
|
9791
9811
|
}
|
|
9792
9812
|
return h.toString(36);
|
|
9793
9813
|
}
|
|
9814
|
+
/**
|
|
9815
|
+
* Validates that a field name is a safe identifier (alphanumeric, underscores, dots for nested paths).
|
|
9816
|
+
* Prevents prompt injection via crafted field names.
|
|
9817
|
+
*/
|
|
9818
|
+
function validateFieldName(field) {
|
|
9819
|
+
if (!/^[a-zA-Z0-9_.]+$/.test(field)) {
|
|
9820
|
+
throw new Error(`Invalid field name "${field}". Field names must only contain letters, numbers, underscores, and dots.`);
|
|
9821
|
+
}
|
|
9822
|
+
}
|
|
9823
|
+
/**
|
|
9824
|
+
* Parses a raw aggregation result (e.g. [{ count: 42 }] or [{ _id: null, total: 100 }])
|
|
9825
|
+
* into a single numeric value.
|
|
9826
|
+
*/
|
|
9827
|
+
function parseAggregateValue(result) {
|
|
9828
|
+
if (typeof result === 'number')
|
|
9829
|
+
return result;
|
|
9830
|
+
if (Array.isArray(result)) {
|
|
9831
|
+
if (result.length === 0)
|
|
9832
|
+
return 0;
|
|
9833
|
+
// Multiple elements — not a collapsed aggregate result
|
|
9834
|
+
if (result.length > 1) {
|
|
9835
|
+
throw new Error(`Unexpected aggregate result: got array with ${result.length} elements. The AI may have returned full documents instead of an aggregation.`);
|
|
9836
|
+
}
|
|
9837
|
+
const first = result[0];
|
|
9838
|
+
if (typeof first === 'number')
|
|
9839
|
+
return first;
|
|
9840
|
+
if (first && typeof first === 'object') {
|
|
9841
|
+
// $count stage returns { count: N }
|
|
9842
|
+
if (typeof first.count === 'number')
|
|
9843
|
+
return first.count;
|
|
9844
|
+
// $group stage returns { _id: null, result: N } — expect _id + one numeric field
|
|
9845
|
+
const numericEntries = Object.entries(first).filter(([key, val]) => key !== '_id' && typeof val === 'number');
|
|
9846
|
+
if (numericEntries.length === 1)
|
|
9847
|
+
return numericEntries[0][1];
|
|
9848
|
+
}
|
|
9849
|
+
// Avoid leaking document contents into error messages
|
|
9850
|
+
const shape = first && typeof first === 'object' ? `{${Object.keys(first).join(', ')}}` : String(first);
|
|
9851
|
+
throw new Error(`Unexpected aggregate result shape: ${shape}. Expected {count: N} or {_id: null, <field>: N}.`);
|
|
9852
|
+
}
|
|
9853
|
+
if (result && typeof result === 'object' && typeof result.count === 'number') {
|
|
9854
|
+
return result.count;
|
|
9855
|
+
}
|
|
9856
|
+
throw new Error(`Unexpected aggregate result type: ${typeof result}. Expected a number, array, or object with a count field.`);
|
|
9857
|
+
}
|
|
9858
|
+
/**
|
|
9859
|
+
* Count items in a collection path. Returns a numeric result.
|
|
9860
|
+
*
|
|
9861
|
+
* This uses the AI query engine with a count-specific prompt prefix,
|
|
9862
|
+
* so TaroBase will generate a $count aggregation pipeline and return
|
|
9863
|
+
* just the count rather than full documents.
|
|
9864
|
+
*
|
|
9865
|
+
* IMPORTANT: This only works for collections where the read policy is "true".
|
|
9866
|
+
* If the read policy requires per-document checks, the server will return
|
|
9867
|
+
* an error because aggregate counts cannot be performed without pulling all
|
|
9868
|
+
* documents for access control evaluation.
|
|
9869
|
+
*
|
|
9870
|
+
* @param path - Collection path (e.g., "posts", "users/abc/comments")
|
|
9871
|
+
* @param opts - Optional filter prompt and overrides
|
|
9872
|
+
* @returns AggregateResult with the count value
|
|
9873
|
+
*/
|
|
9874
|
+
async function count(path, opts = {}) {
|
|
9875
|
+
const prefix = 'Return ONLY the total count of matching documents. Use the $count stage to produce a field named "count". Do NOT return the documents themselves.';
|
|
9876
|
+
const fullPrompt = opts.prompt
|
|
9877
|
+
? `${prefix} Filter: ${opts.prompt}`
|
|
9878
|
+
: prefix;
|
|
9879
|
+
const result = await get$2(path, { prompt: fullPrompt, bypassCache: true, _overrides: opts._overrides });
|
|
9880
|
+
return { value: parseAggregateValue(result) };
|
|
9881
|
+
}
|
|
9882
|
+
/**
|
|
9883
|
+
* Run an aggregate operation on a collection path. Returns a numeric result.
|
|
9884
|
+
*
|
|
9885
|
+
* Supported operations:
|
|
9886
|
+
* - count: Total number of documents
|
|
9887
|
+
* - uniqueCount: Number of distinct values for a field
|
|
9888
|
+
* - sum: Sum of a numeric field
|
|
9889
|
+
* - avg: Average of a numeric field
|
|
9890
|
+
* - min: Minimum value of a numeric field
|
|
9891
|
+
* - max: Maximum value of a numeric field
|
|
9892
|
+
*
|
|
9893
|
+
* IMPORTANT: This only works for collections where the read policy is "true".
|
|
9894
|
+
* If the read policy requires per-document checks, the server will return
|
|
9895
|
+
* an error because aggregate operations cannot be performed without pulling
|
|
9896
|
+
* all documents for access control evaluation.
|
|
9897
|
+
*
|
|
9898
|
+
* @param path - Collection path (e.g., "posts", "users/abc/comments")
|
|
9899
|
+
* @param operation - The aggregate operation to perform
|
|
9900
|
+
* @param opts - Options including optional filter prompt and field name
|
|
9901
|
+
* @returns AggregateResult with the computed numeric value
|
|
9902
|
+
*/
|
|
9903
|
+
async function aggregate(path, operation, opts = {}) {
|
|
9904
|
+
let prefix;
|
|
9905
|
+
switch (operation) {
|
|
9906
|
+
case 'count':
|
|
9907
|
+
prefix = 'Return ONLY the total count of matching documents. Use the $count stage to produce a field named "count". Do NOT return the documents themselves.';
|
|
9908
|
+
break;
|
|
9909
|
+
case 'uniqueCount':
|
|
9910
|
+
if (!opts.field)
|
|
9911
|
+
throw new Error('aggregate "uniqueCount" requires a field option');
|
|
9912
|
+
validateFieldName(opts.field);
|
|
9913
|
+
prefix = `Return ONLY the count of unique/distinct values of the "${opts.field}" field. Use $group with _id set to "$${opts.field}" then $count to produce a field named "count". Do NOT return the documents themselves.`;
|
|
9914
|
+
break;
|
|
9915
|
+
case 'sum':
|
|
9916
|
+
if (!opts.field)
|
|
9917
|
+
throw new Error('aggregate "sum" requires a field option');
|
|
9918
|
+
validateFieldName(opts.field);
|
|
9919
|
+
prefix = `Return ONLY the sum of the "${opts.field}" field across all matching documents. Use $group with _id: null and result: { $sum: "$${opts.field}" }. Do NOT return the documents themselves.`;
|
|
9920
|
+
break;
|
|
9921
|
+
case 'avg':
|
|
9922
|
+
if (!opts.field)
|
|
9923
|
+
throw new Error('aggregate "avg" requires a field option');
|
|
9924
|
+
validateFieldName(opts.field);
|
|
9925
|
+
prefix = `Return ONLY the average of the "${opts.field}" field across all matching documents. Use $group with _id: null and result: { $avg: "$${opts.field}" }. Do NOT return the documents themselves.`;
|
|
9926
|
+
break;
|
|
9927
|
+
case 'min':
|
|
9928
|
+
if (!opts.field)
|
|
9929
|
+
throw new Error('aggregate "min" requires a field option');
|
|
9930
|
+
validateFieldName(opts.field);
|
|
9931
|
+
prefix = `Return ONLY the minimum value of the "${opts.field}" field across all matching documents. Use $group with _id: null and result: { $min: "$${opts.field}" }. Do NOT return the documents themselves.`;
|
|
9932
|
+
break;
|
|
9933
|
+
case 'max':
|
|
9934
|
+
if (!opts.field)
|
|
9935
|
+
throw new Error('aggregate "max" requires a field option');
|
|
9936
|
+
validateFieldName(opts.field);
|
|
9937
|
+
prefix = `Return ONLY the maximum value of the "${opts.field}" field across all matching documents. Use $group with _id: null and result: { $max: "$${opts.field}" }. Do NOT return the documents themselves.`;
|
|
9938
|
+
break;
|
|
9939
|
+
default:
|
|
9940
|
+
throw new Error(`Unsupported aggregate operation: ${operation}`);
|
|
9941
|
+
}
|
|
9942
|
+
const fullPrompt = opts.prompt
|
|
9943
|
+
? `${prefix} Filter: ${opts.prompt}`
|
|
9944
|
+
: prefix;
|
|
9945
|
+
const result = await get$2(path, { prompt: fullPrompt, bypassCache: true, _overrides: opts._overrides });
|
|
9946
|
+
// For uniqueCount, the AI may return $group results without the final $count
|
|
9947
|
+
// stage, producing [{_id: "val1"}, {_id: "val2"}, ...]. Verify elements look
|
|
9948
|
+
// like $group output (only _id key) before using array length as the count.
|
|
9949
|
+
if (operation === 'uniqueCount' && Array.isArray(result) && result.length > 1) {
|
|
9950
|
+
const looksLikeGroupOutput = result.every((el) => el && typeof el === 'object' && Object.keys(el).length === 1 && '_id' in el);
|
|
9951
|
+
if (looksLikeGroupOutput) {
|
|
9952
|
+
return { value: result.length };
|
|
9953
|
+
}
|
|
9954
|
+
throw new Error(`Unexpected uniqueCount result: got ${result.length} elements that don't match $group output shape.`);
|
|
9955
|
+
}
|
|
9956
|
+
return { value: parseAggregateValue(result) };
|
|
9957
|
+
}
|
|
9794
9958
|
async function get$2(path, opts = {}) {
|
|
9795
9959
|
try {
|
|
9796
9960
|
let normalizedPath = path.startsWith("/") ? path.slice(1) : path;
|
|
@@ -10257,7 +10421,7 @@ const BASE_MIN_RECONNECT_DELAY_MS = 1000;
|
|
|
10257
10421
|
const MIN_RECONNECT_DELAY_JITTER_MS = 1000;
|
|
10258
10422
|
const MAX_RECONNECT_DELAY_MS = 300000;
|
|
10259
10423
|
const RECONNECT_DELAY_GROW_FACTOR = 1.8;
|
|
10260
|
-
const MIN_BROWSER_RECONNECT_INTERVAL_MS =
|
|
10424
|
+
const MIN_BROWSER_RECONNECT_INTERVAL_MS = 5000;
|
|
10261
10425
|
const WS_CONFIG = {
|
|
10262
10426
|
// Keep retrying indefinitely so long outages recover without page refresh.
|
|
10263
10427
|
maxRetries: Infinity,
|
|
@@ -10422,6 +10586,8 @@ async function getOrCreateConnection(appId, isServer) {
|
|
|
10422
10586
|
isConnected: false,
|
|
10423
10587
|
appId,
|
|
10424
10588
|
tokenRefreshTimer: null,
|
|
10589
|
+
lastMessageAt: Date.now(),
|
|
10590
|
+
keepaliveTimer: null,
|
|
10425
10591
|
};
|
|
10426
10592
|
connections.set(appId, connection);
|
|
10427
10593
|
// URL provider for reconnection with fresh tokens
|
|
@@ -10458,6 +10624,7 @@ async function getOrCreateConnection(appId, isServer) {
|
|
|
10458
10624
|
ws.addEventListener('open', () => {
|
|
10459
10625
|
connection.isConnecting = false;
|
|
10460
10626
|
connection.isConnected = true;
|
|
10627
|
+
connection.lastMessageAt = Date.now();
|
|
10461
10628
|
// Schedule token refresh before expiry
|
|
10462
10629
|
(async () => {
|
|
10463
10630
|
const token = await getIdToken$1(isServer);
|
|
@@ -10465,11 +10632,28 @@ async function getOrCreateConnection(appId, isServer) {
|
|
|
10465
10632
|
})();
|
|
10466
10633
|
// Re-subscribe to all existing subscriptions after reconnect
|
|
10467
10634
|
for (const sub of connection.subscriptions.values()) {
|
|
10635
|
+
sub.lastData = undefined;
|
|
10468
10636
|
sendSubscribe(connection, sub);
|
|
10469
10637
|
}
|
|
10638
|
+
// Start keepalive detection — if no messages for 90s, force reconnect
|
|
10639
|
+
if (connection.keepaliveTimer) {
|
|
10640
|
+
clearInterval(connection.keepaliveTimer);
|
|
10641
|
+
}
|
|
10642
|
+
connection.keepaliveTimer = setInterval(() => {
|
|
10643
|
+
var _a;
|
|
10644
|
+
if (Date.now() - connection.lastMessageAt > 90000) {
|
|
10645
|
+
console.warn('[WS v2] No messages received for 90s, forcing reconnect');
|
|
10646
|
+
if (connection.keepaliveTimer) {
|
|
10647
|
+
clearInterval(connection.keepaliveTimer);
|
|
10648
|
+
connection.keepaliveTimer = null;
|
|
10649
|
+
}
|
|
10650
|
+
(_a = connection.ws) === null || _a === void 0 ? void 0 : _a.reconnect();
|
|
10651
|
+
}
|
|
10652
|
+
}, 30000);
|
|
10470
10653
|
});
|
|
10471
10654
|
// Handle incoming messages
|
|
10472
10655
|
ws.addEventListener('message', (event) => {
|
|
10656
|
+
connection.lastMessageAt = Date.now();
|
|
10473
10657
|
try {
|
|
10474
10658
|
const message = JSON.parse(event.data);
|
|
10475
10659
|
handleServerMessage(connection, message);
|
|
@@ -10481,20 +10665,22 @@ async function getOrCreateConnection(appId, isServer) {
|
|
|
10481
10665
|
// Handle errors
|
|
10482
10666
|
ws.addEventListener('error', (event) => {
|
|
10483
10667
|
console.error('[WS v2] WebSocket error:', event);
|
|
10484
|
-
|
|
10485
|
-
for (const [id, pending] of connection.pendingSubscriptions) {
|
|
10668
|
+
for (const [, pending] of connection.pendingSubscriptions) {
|
|
10486
10669
|
pending.reject(new Error('WebSocket error'));
|
|
10487
|
-
connection.pendingSubscriptions.delete(id);
|
|
10488
10670
|
}
|
|
10671
|
+
connection.pendingSubscriptions.clear();
|
|
10489
10672
|
});
|
|
10490
10673
|
// Handle close
|
|
10491
10674
|
ws.addEventListener('close', () => {
|
|
10492
10675
|
connection.isConnected = false;
|
|
10493
|
-
// Clear token refresh timer
|
|
10494
10676
|
if (connection.tokenRefreshTimer) {
|
|
10495
10677
|
clearTimeout(connection.tokenRefreshTimer);
|
|
10496
10678
|
connection.tokenRefreshTimer = null;
|
|
10497
10679
|
}
|
|
10680
|
+
if (connection.keepaliveTimer) {
|
|
10681
|
+
clearInterval(connection.keepaliveTimer);
|
|
10682
|
+
connection.keepaliveTimer = null;
|
|
10683
|
+
}
|
|
10498
10684
|
});
|
|
10499
10685
|
return connection;
|
|
10500
10686
|
}
|
|
@@ -10694,9 +10880,7 @@ async function subscribeV2(path, subscriptionOptions) {
|
|
|
10694
10880
|
await subscriptionPromise;
|
|
10695
10881
|
}
|
|
10696
10882
|
catch (error) {
|
|
10697
|
-
|
|
10698
|
-
connection.subscriptions.delete(subscriptionId);
|
|
10699
|
-
throw error;
|
|
10883
|
+
console.warn('[WS v2] Subscription confirmation failed, keeping for reconnect recovery:', error);
|
|
10700
10884
|
}
|
|
10701
10885
|
}
|
|
10702
10886
|
// Return unsubscribe function
|
|
@@ -10812,8 +10996,6 @@ async function reconnectWithNewAuthV2() {
|
|
|
10812
10996
|
if (!connection.ws) {
|
|
10813
10997
|
continue;
|
|
10814
10998
|
}
|
|
10815
|
-
// Reject any pending subscriptions - they'll need to be retried after reconnect
|
|
10816
|
-
// This prevents hanging promises during auth transitions
|
|
10817
10999
|
for (const [, pending] of connection.pendingSubscriptions) {
|
|
10818
11000
|
pending.reject(new Error('Connection reconnecting due to auth change'));
|
|
10819
11001
|
}
|
|
@@ -13345,7 +13527,7 @@ async function loadDependencies() {
|
|
|
13345
13527
|
const [reactModule, reactDomModule, phantomModule] = await Promise.all([
|
|
13346
13528
|
import('react'),
|
|
13347
13529
|
import('react-dom/client'),
|
|
13348
|
-
Promise.resolve().then(function () { return require('./index-
|
|
13530
|
+
Promise.resolve().then(function () { return require('./index-BmJDdk1y.js'); })
|
|
13349
13531
|
]);
|
|
13350
13532
|
// Extract default export from ESM module namespace
|
|
13351
13533
|
// Dynamic import() returns { default: Module, ...exports }, not the module directly
|
|
@@ -33327,13 +33509,21 @@ class PrivyWalletProvider {
|
|
|
33327
33509
|
await this.privyMethods.logout();
|
|
33328
33510
|
}
|
|
33329
33511
|
async runTransaction(_evmTransactionData, solTransactionData, options) {
|
|
33330
|
-
var _a, _b;
|
|
33512
|
+
var _a, _b, _c;
|
|
33331
33513
|
await this.ensureReady({ waitForWallets: true });
|
|
33332
33514
|
let session = await WebSessionManager.getSession();
|
|
33333
33515
|
let sessionAddress = session === null || session === void 0 ? void 0 : session.address;
|
|
33334
33516
|
let privyWallets = (_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.wallets;
|
|
33335
33517
|
let privyWallet = privyWallets === null || privyWallets === void 0 ? void 0 : privyWallets.find((wallet) => wallet.address === sessionAddress);
|
|
33518
|
+
// If wallet not found yet, it may be an embedded wallet (email login) that hasn't
|
|
33519
|
+
// appeared in the wallets array due to React state timing. Wait for it before
|
|
33520
|
+
// falling back to connectWallet() which shows an unwanted wallet selection modal.
|
|
33336
33521
|
if (!privyWallets || privyWallets.length === 0 || !privyWallet) {
|
|
33522
|
+
if (((_b = this.privyMethods) === null || _b === void 0 ? void 0 : _b.authenticated) && sessionAddress) {
|
|
33523
|
+
privyWallet = await this.waitForMatchingWallet(sessionAddress);
|
|
33524
|
+
}
|
|
33525
|
+
}
|
|
33526
|
+
if (!privyWallet) {
|
|
33337
33527
|
// If there's already a pending transaction, throw an error to prevent overlapping calls
|
|
33338
33528
|
if (this.pendingTransaction) {
|
|
33339
33529
|
throw new Error("Oops... something went wrong. Please try again.");
|
|
@@ -33413,7 +33603,7 @@ class PrivyWalletProvider {
|
|
|
33413
33603
|
return {
|
|
33414
33604
|
transactionSignature: signature,
|
|
33415
33605
|
blockNumber: (txInfo === null || txInfo === void 0 ? void 0 : txInfo.slot) || 0,
|
|
33416
|
-
gasUsed: ((
|
|
33606
|
+
gasUsed: ((_c = txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta) === null || _c === void 0 ? void 0 : _c.fee.toString()) || '0',
|
|
33417
33607
|
data: txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta,
|
|
33418
33608
|
};
|
|
33419
33609
|
}
|
|
@@ -33433,7 +33623,7 @@ class PrivyWalletProvider {
|
|
|
33433
33623
|
* @returns The signed transaction
|
|
33434
33624
|
*/
|
|
33435
33625
|
async signTransaction(transaction) {
|
|
33436
|
-
var _a;
|
|
33626
|
+
var _a, _b;
|
|
33437
33627
|
await this.ensureReady({ waitForWallets: true });
|
|
33438
33628
|
let privyWallets = (_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.wallets;
|
|
33439
33629
|
let session = await WebSessionManager.getSession();
|
|
@@ -33443,8 +33633,16 @@ class PrivyWalletProvider {
|
|
|
33443
33633
|
if (this.pendingSignTransaction) {
|
|
33444
33634
|
throw new Error("Oops... something went wrong. Please try again.");
|
|
33445
33635
|
}
|
|
33446
|
-
// If wallet not
|
|
33636
|
+
// If wallet not found yet, it may be an embedded wallet (email login) that hasn't
|
|
33637
|
+
// appeared in the wallets array due to React state timing. Wait for it before
|
|
33638
|
+
// falling back to connectWallet() which shows an unwanted wallet selection modal.
|
|
33447
33639
|
if (!privyWallets || privyWallets.length === 0 || !privyWallet) {
|
|
33640
|
+
if (((_b = this.privyMethods) === null || _b === void 0 ? void 0 : _b.authenticated) && sessionAddress) {
|
|
33641
|
+
privyWallet = await this.waitForMatchingWallet(sessionAddress);
|
|
33642
|
+
}
|
|
33643
|
+
}
|
|
33644
|
+
// If still no wallet after waiting, trigger connection and queue the signing
|
|
33645
|
+
if (!privyWallet) {
|
|
33448
33646
|
return new Promise((resolve, reject) => {
|
|
33449
33647
|
this.pendingSignTransaction = {
|
|
33450
33648
|
resolve,
|
|
@@ -33507,7 +33705,7 @@ class PrivyWalletProvider {
|
|
|
33507
33705
|
* @returns The transaction signature
|
|
33508
33706
|
*/
|
|
33509
33707
|
async signAndSubmitTransaction(transaction, feePayer) {
|
|
33510
|
-
var _a;
|
|
33708
|
+
var _a, _b;
|
|
33511
33709
|
await this.ensureReady({ waitForWallets: true });
|
|
33512
33710
|
let privyWallets = (_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.wallets;
|
|
33513
33711
|
let session = await WebSessionManager.getSession();
|
|
@@ -33517,8 +33715,16 @@ class PrivyWalletProvider {
|
|
|
33517
33715
|
if (this.pendingSignAndSubmitTransaction) {
|
|
33518
33716
|
throw new Error("Oops... something went wrong. Please try again.");
|
|
33519
33717
|
}
|
|
33520
|
-
// If wallet not
|
|
33718
|
+
// If wallet not found yet, it may be an embedded wallet (email login) that hasn't
|
|
33719
|
+
// appeared in the wallets array due to React state timing. Wait for it before
|
|
33720
|
+
// falling back to connectWallet() which shows an unwanted wallet selection modal.
|
|
33521
33721
|
if (!privyWallets || privyWallets.length === 0 || !privyWallet) {
|
|
33722
|
+
if (((_b = this.privyMethods) === null || _b === void 0 ? void 0 : _b.authenticated) && sessionAddress) {
|
|
33723
|
+
privyWallet = await this.waitForMatchingWallet(sessionAddress);
|
|
33724
|
+
}
|
|
33725
|
+
}
|
|
33726
|
+
// If still no wallet after waiting, trigger connection and queue the signing
|
|
33727
|
+
if (!privyWallet) {
|
|
33522
33728
|
return new Promise((resolve, reject) => {
|
|
33523
33729
|
this.pendingSignAndSubmitTransaction = {
|
|
33524
33730
|
resolve,
|
|
@@ -33684,7 +33890,7 @@ class PrivyWalletProvider {
|
|
|
33684
33890
|
return { signature, txInfo };
|
|
33685
33891
|
}
|
|
33686
33892
|
async signMessage(message) {
|
|
33687
|
-
var _a, _b;
|
|
33893
|
+
var _a, _b, _c;
|
|
33688
33894
|
await this.ensureReady({ waitForWallets: true });
|
|
33689
33895
|
const session = await WebSessionManager.getSession();
|
|
33690
33896
|
let sessionAddress = session === null || session === void 0 ? void 0 : session.address;
|
|
@@ -33692,23 +33898,47 @@ class PrivyWalletProvider {
|
|
|
33692
33898
|
if (this.pendingSignMessage) {
|
|
33693
33899
|
throw new Error("Oops... something went wrong. Please try again.");
|
|
33694
33900
|
}
|
|
33695
|
-
// If no wallets connected,
|
|
33901
|
+
// If no wallets connected yet, it may be an embedded wallet (email login) that hasn't
|
|
33902
|
+
// appeared in the wallets array due to React state timing. Wait for it before
|
|
33903
|
+
// falling back to connectWallet() which shows an unwanted wallet selection modal.
|
|
33696
33904
|
if (!((_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.wallets) || this.privyMethods.wallets.length === 0) {
|
|
33697
|
-
|
|
33698
|
-
|
|
33699
|
-
|
|
33700
|
-
reject
|
|
33701
|
-
|
|
33702
|
-
|
|
33703
|
-
|
|
33704
|
-
|
|
33705
|
-
|
|
33706
|
-
|
|
33707
|
-
|
|
33708
|
-
|
|
33709
|
-
|
|
33710
|
-
|
|
33711
|
-
|
|
33905
|
+
if (((_b = this.privyMethods) === null || _b === void 0 ? void 0 : _b.authenticated) && sessionAddress) {
|
|
33906
|
+
const matchedWallet = await this.waitForMatchingWallet(sessionAddress);
|
|
33907
|
+
if (!matchedWallet) {
|
|
33908
|
+
return new Promise((resolve, reject) => {
|
|
33909
|
+
this.pendingSignMessage = {
|
|
33910
|
+
resolve,
|
|
33911
|
+
reject,
|
|
33912
|
+
message
|
|
33913
|
+
};
|
|
33914
|
+
this.privyMethods.connectWallet();
|
|
33915
|
+
// Set a timeout to reject the promise if connection takes too long
|
|
33916
|
+
setTimeout(() => {
|
|
33917
|
+
if (this.pendingSignMessage) {
|
|
33918
|
+
this.pendingSignMessage.reject(new Error("Wallet connection timed out"));
|
|
33919
|
+
this.pendingSignMessage = null;
|
|
33920
|
+
}
|
|
33921
|
+
}, 30000); // 30 seconds timeout
|
|
33922
|
+
});
|
|
33923
|
+
}
|
|
33924
|
+
}
|
|
33925
|
+
else {
|
|
33926
|
+
return new Promise((resolve, reject) => {
|
|
33927
|
+
this.pendingSignMessage = {
|
|
33928
|
+
resolve,
|
|
33929
|
+
reject,
|
|
33930
|
+
message
|
|
33931
|
+
};
|
|
33932
|
+
this.privyMethods.connectWallet();
|
|
33933
|
+
// Set a timeout to reject the promise if connection takes too long
|
|
33934
|
+
setTimeout(() => {
|
|
33935
|
+
if (this.pendingSignMessage) {
|
|
33936
|
+
this.pendingSignMessage.reject(new Error("Wallet connection timed out"));
|
|
33937
|
+
this.pendingSignMessage = null;
|
|
33938
|
+
}
|
|
33939
|
+
}, 30000); // 30 seconds timeout
|
|
33940
|
+
});
|
|
33941
|
+
}
|
|
33712
33942
|
}
|
|
33713
33943
|
let privyWallet = this.privyMethods.wallets.find((wallet) => wallet.address === sessionAddress);
|
|
33714
33944
|
if (!privyWallet) {
|
|
@@ -33726,7 +33956,7 @@ class PrivyWalletProvider {
|
|
|
33726
33956
|
// Use the Privy signMessage hook for Solana wallets
|
|
33727
33957
|
// The message needs to be passed as a Uint8Array
|
|
33728
33958
|
const messageBytes = new TextEncoder().encode(message);
|
|
33729
|
-
const result = await ((
|
|
33959
|
+
const result = await ((_c = this.privyMethods) === null || _c === void 0 ? void 0 : _c.signMessage({
|
|
33730
33960
|
message: messageBytes,
|
|
33731
33961
|
wallet: privyWallet,
|
|
33732
33962
|
}));
|
|
@@ -33751,6 +33981,25 @@ class PrivyWalletProvider {
|
|
|
33751
33981
|
const createSessionResult = await createSessionWithPrivy(accessToken, address, idToken);
|
|
33752
33982
|
await WebSessionManager.storeSession(address, createSessionResult.accessToken, createSessionResult.idToken, createSessionResult.refreshToken);
|
|
33753
33983
|
}
|
|
33984
|
+
/**
|
|
33985
|
+
* Waits for a wallet matching the session address to appear in the wallets array.
|
|
33986
|
+
* This handles the timing gap where Privy's embedded wallet (created for email login users)
|
|
33987
|
+
* may not yet be in the useWallets() array when signTransaction is called immediately after login.
|
|
33988
|
+
*/
|
|
33989
|
+
async waitForMatchingWallet(sessionAddress, timeoutMs = 10000) {
|
|
33990
|
+
var _a;
|
|
33991
|
+
const startTime = Date.now();
|
|
33992
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
33993
|
+
const wallets = (_a = this.privyMethods) === null || _a === void 0 ? void 0 : _a.wallets;
|
|
33994
|
+
if (wallets && wallets.length > 0) {
|
|
33995
|
+
const wallet = wallets.find((w) => w.address === sessionAddress);
|
|
33996
|
+
if (wallet)
|
|
33997
|
+
return wallet;
|
|
33998
|
+
}
|
|
33999
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
34000
|
+
}
|
|
34001
|
+
return null;
|
|
34002
|
+
}
|
|
33754
34003
|
async ensureReady({ waitForWallets = false, timeoutMs = 15000 } = {}) {
|
|
33755
34004
|
const isReady = () => {
|
|
33756
34005
|
var _a, _b;
|
|
@@ -34949,12 +35198,14 @@ exports.PhantomWalletProvider = PhantomWalletProvider;
|
|
|
34949
35198
|
exports.PrivyWalletProvider = PrivyWalletProvider;
|
|
34950
35199
|
exports.ServerSessionManager = ServerSessionManager;
|
|
34951
35200
|
exports.WebSessionManager = WebSessionManager;
|
|
35201
|
+
exports.aggregate = aggregate;
|
|
34952
35202
|
exports.bs58 = bs58;
|
|
34953
35203
|
exports.bufferExports = bufferExports;
|
|
34954
35204
|
exports.buildSetDocumentsTransaction = buildSetDocumentsTransaction;
|
|
34955
35205
|
exports.clearCache = clearCache;
|
|
34956
35206
|
exports.closeAllSubscriptions = closeAllSubscriptions;
|
|
34957
35207
|
exports.convertRemainingAccounts = convertRemainingAccounts;
|
|
35208
|
+
exports.count = count;
|
|
34958
35209
|
exports.createSessionWithPrivy = createSessionWithPrivy;
|
|
34959
35210
|
exports.createSessionWithSignature = createSessionWithSignature;
|
|
34960
35211
|
exports.genAuthNonce = genAuthNonce;
|
|
@@ -34987,4 +35238,4 @@ exports.signSessionCreateMessage = signSessionCreateMessage;
|
|
|
34987
35238
|
exports.signTransaction = signTransaction;
|
|
34988
35239
|
exports.subscribe = subscribe;
|
|
34989
35240
|
exports.useAuth = useAuth;
|
|
34990
|
-
//# sourceMappingURL=index-
|
|
35241
|
+
//# sourceMappingURL=index-9kQbe-Gv.js.map
|