@pooflabs/core 0.0.39 → 0.0.40
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/client/config.d.ts +4 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +222 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +222 -7
- package/dist/index.mjs.map +1 -1
- package/dist/utils/core-platform.d.ts +16 -0
- package/dist/utils/rn-session-manager.d.ts +73 -0
- package/dist/utils/web-session-manager.d.ts +5 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -42,7 +42,12 @@ async function createSessionWithSignature(address, message, signature) {
|
|
|
42
42
|
return response.data;
|
|
43
43
|
}
|
|
44
44
|
async function createSessionWithPrivy(authToken, address, privyIdToken) {
|
|
45
|
-
|
|
45
|
+
var _a;
|
|
46
|
+
// Block in true SSR/Node.js. Allow in browser (window exists) and React Native (no window,
|
|
47
|
+
// but not Node — detected via process.versions.node). Node 21+ defines navigator globally,
|
|
48
|
+
// so we can't rely on navigator alone.
|
|
49
|
+
const isNode = typeof process !== 'undefined' && !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);
|
|
50
|
+
if (typeof window === 'undefined' && isNode)
|
|
46
51
|
return;
|
|
47
52
|
const client = await getAxiosAuthClient();
|
|
48
53
|
const config = await getConfig();
|
|
@@ -70,6 +75,19 @@ async function signSessionCreateMessage(_signMessageFunction) {
|
|
|
70
75
|
}
|
|
71
76
|
|
|
72
77
|
class WebSessionManager {
|
|
78
|
+
/**
|
|
79
|
+
* Decode a base64url-encoded string (used by JWT payloads).
|
|
80
|
+
* Normalises base64url → standard base64 before calling browser atob().
|
|
81
|
+
*/
|
|
82
|
+
static decodeBase64Url(input) {
|
|
83
|
+
let b64 = input.replace(/-/g, '+').replace(/_/g, '/');
|
|
84
|
+
const pad = b64.length % 4;
|
|
85
|
+
if (pad === 2)
|
|
86
|
+
b64 += '==';
|
|
87
|
+
else if (pad === 3)
|
|
88
|
+
b64 += '=';
|
|
89
|
+
return atob(b64);
|
|
90
|
+
}
|
|
73
91
|
/* ------------------------------------------------------------------ */
|
|
74
92
|
/* STORE */
|
|
75
93
|
/* ------------------------------------------------------------------ */
|
|
@@ -105,7 +123,7 @@ class WebSessionManager {
|
|
|
105
123
|
/* ---------- check JWT expiration ---------- */
|
|
106
124
|
try {
|
|
107
125
|
const { accessToken } = sessionObj;
|
|
108
|
-
const { exp } = JSON.parse(
|
|
126
|
+
const { exp } = JSON.parse(this.decodeBase64Url(accessToken.split(".")[1]));
|
|
109
127
|
if (Date.now() > exp * 1000) {
|
|
110
128
|
const { refreshToken } = sessionObj;
|
|
111
129
|
if (!refreshToken)
|
|
@@ -3119,6 +3137,41 @@ var serverSessionManager = /*#__PURE__*/Object.freeze({
|
|
|
3119
3137
|
ServerSessionManager: ServerSessionManager
|
|
3120
3138
|
});
|
|
3121
3139
|
|
|
3140
|
+
/**
|
|
3141
|
+
* Safe base64 helpers for tarobase-core.
|
|
3142
|
+
*
|
|
3143
|
+
* Uses the global atob/btoa when available (browser, RN with polyfill),
|
|
3144
|
+
* falls back to the 'buffer' package (Node.js / SSR / RN without polyfill).
|
|
3145
|
+
*
|
|
3146
|
+
* These are used instead of bare `atob()`/`btoa()` so the core package
|
|
3147
|
+
* works in React Native without requiring the consumer to polyfill globals.
|
|
3148
|
+
*/
|
|
3149
|
+
function safeAtob(input) {
|
|
3150
|
+
if (typeof globalThis.atob === 'function') {
|
|
3151
|
+
return globalThis.atob(input);
|
|
3152
|
+
}
|
|
3153
|
+
return bufferExports.Buffer.from(input, 'base64').toString('binary');
|
|
3154
|
+
}
|
|
3155
|
+
function safeBtoa(input) {
|
|
3156
|
+
if (typeof globalThis.btoa === 'function') {
|
|
3157
|
+
return globalThis.btoa(input);
|
|
3158
|
+
}
|
|
3159
|
+
return bufferExports.Buffer.from(input, 'binary').toString('base64');
|
|
3160
|
+
}
|
|
3161
|
+
/**
|
|
3162
|
+
* Decode a base64url-encoded string (used by JWT payloads).
|
|
3163
|
+
* Normalises base64url → standard base64 before decoding.
|
|
3164
|
+
*/
|
|
3165
|
+
function decodeBase64Url(input) {
|
|
3166
|
+
let b64 = input.replace(/-/g, '+').replace(/_/g, '/');
|
|
3167
|
+
const pad = b64.length % 4;
|
|
3168
|
+
if (pad === 2)
|
|
3169
|
+
b64 += '==';
|
|
3170
|
+
else if (pad === 3)
|
|
3171
|
+
b64 += '=';
|
|
3172
|
+
return safeAtob(b64);
|
|
3173
|
+
}
|
|
3174
|
+
|
|
3122
3175
|
async function createBearerToken(isServer) {
|
|
3123
3176
|
if (isServer) {
|
|
3124
3177
|
const sessionMgr = ServerSessionManager.instance;
|
|
@@ -3618,7 +3671,7 @@ async function get(path, opts = {}) {
|
|
|
3618
3671
|
}
|
|
3619
3672
|
else {
|
|
3620
3673
|
const path = encodeURIComponent(normalizedPath);
|
|
3621
|
-
const promptQueryParam = (opts === null || opts === void 0 ? void 0 : opts.prompt) ? `&prompt=${
|
|
3674
|
+
const promptQueryParam = (opts === null || opts === void 0 ? void 0 : opts.prompt) ? `&prompt=${safeBtoa(opts.prompt)}` : "";
|
|
3622
3675
|
const apiPath = `items?path=${path}${promptQueryParam}${includeSubPathsParam}${shapeParam}${limitParam}${cursorParam}`;
|
|
3623
3676
|
response = await makeApiRequest('GET', apiPath, null, opts._overrides);
|
|
3624
3677
|
}
|
|
@@ -4073,7 +4126,7 @@ function getCacheKey(path, prompt, shape, limit, cursor) {
|
|
|
4073
4126
|
}
|
|
4074
4127
|
function isTokenExpired(token) {
|
|
4075
4128
|
try {
|
|
4076
|
-
const payload = JSON.parse(
|
|
4129
|
+
const payload = JSON.parse(decodeBase64Url(token.split('.')[1]));
|
|
4077
4130
|
const expirationTime = payload.exp * 1000;
|
|
4078
4131
|
const currentTime = Date.now();
|
|
4079
4132
|
return currentTime > (expirationTime - 60000); // 60 second buffer
|
|
@@ -4085,7 +4138,7 @@ function isTokenExpired(token) {
|
|
|
4085
4138
|
}
|
|
4086
4139
|
function getTokenExpirationTime(token) {
|
|
4087
4140
|
try {
|
|
4088
|
-
const payload = JSON.parse(
|
|
4141
|
+
const payload = JSON.parse(decodeBase64Url(token.split('.')[1]));
|
|
4089
4142
|
return payload.exp ? payload.exp * 1000 : null;
|
|
4090
4143
|
}
|
|
4091
4144
|
catch (_a) {
|
|
@@ -4413,7 +4466,7 @@ function sendSubscribe(connection, subscription) {
|
|
|
4413
4466
|
type: 'subscribe',
|
|
4414
4467
|
subscriptionId: subscription.subscriptionId,
|
|
4415
4468
|
path: subscription.path,
|
|
4416
|
-
prompt: subscription.prompt ?
|
|
4469
|
+
prompt: subscription.prompt ? safeBtoa(subscription.prompt) : undefined,
|
|
4417
4470
|
includeSubPaths: subscription.includeSubPaths,
|
|
4418
4471
|
shape: subscription.shape && Object.keys(subscription.shape).length > 0
|
|
4419
4472
|
? subscription.shape
|
|
@@ -4739,5 +4792,167 @@ async function reconnectWithNewAuth() {
|
|
|
4739
4792
|
return reconnectWithNewAuthV2();
|
|
4740
4793
|
}
|
|
4741
4794
|
|
|
4742
|
-
|
|
4795
|
+
let _config = null;
|
|
4796
|
+
class ReactNativeSessionManager {
|
|
4797
|
+
/**
|
|
4798
|
+
* Must be called once before any other method.
|
|
4799
|
+
*
|
|
4800
|
+
* ```ts
|
|
4801
|
+
* import { ReactNativeSessionManager } from '@pooflabs/core';
|
|
4802
|
+
* import { MMKV } from 'react-native-mmkv';
|
|
4803
|
+
* import { decode } from 'base-64';
|
|
4804
|
+
*
|
|
4805
|
+
* const mmkv = new MMKV();
|
|
4806
|
+
* ReactNativeSessionManager.configure({
|
|
4807
|
+
* storage: {
|
|
4808
|
+
* getItem: (k) => mmkv.getString(k) ?? null,
|
|
4809
|
+
* setItem: (k, v) => mmkv.set(k, v),
|
|
4810
|
+
* removeItem: (k) => mmkv.delete(k),
|
|
4811
|
+
* },
|
|
4812
|
+
* atob: decode,
|
|
4813
|
+
* });
|
|
4814
|
+
* ```
|
|
4815
|
+
*/
|
|
4816
|
+
static configure(cfg) {
|
|
4817
|
+
_config = cfg;
|
|
4818
|
+
}
|
|
4819
|
+
static getStorage() {
|
|
4820
|
+
if (!_config) {
|
|
4821
|
+
throw new Error("ReactNativeSessionManager.configure() must be called before using session methods.");
|
|
4822
|
+
}
|
|
4823
|
+
return _config.storage;
|
|
4824
|
+
}
|
|
4825
|
+
static decodeBase64(input) {
|
|
4826
|
+
if (!_config) {
|
|
4827
|
+
throw new Error("ReactNativeSessionManager.configure() must be called before using session methods.");
|
|
4828
|
+
}
|
|
4829
|
+
return _config.atob(input);
|
|
4830
|
+
}
|
|
4831
|
+
/**
|
|
4832
|
+
* Decode a base64url-encoded string (used by JWT payloads).
|
|
4833
|
+
* Normalises base64url → standard base64 before decoding.
|
|
4834
|
+
*/
|
|
4835
|
+
static decodeBase64Url(input) {
|
|
4836
|
+
let b64 = input.replace(/-/g, '+').replace(/_/g, '/');
|
|
4837
|
+
const pad = b64.length % 4;
|
|
4838
|
+
if (pad === 2)
|
|
4839
|
+
b64 += '==';
|
|
4840
|
+
else if (pad === 3)
|
|
4841
|
+
b64 += '=';
|
|
4842
|
+
return this.decodeBase64(b64);
|
|
4843
|
+
}
|
|
4844
|
+
/* ------------------------------------------------------------------ */
|
|
4845
|
+
/* STORE */
|
|
4846
|
+
/* ------------------------------------------------------------------ */
|
|
4847
|
+
static async storeSession(address, accessToken, idToken, refreshToken) {
|
|
4848
|
+
const config = await getConfig();
|
|
4849
|
+
const currentAppId = config.appId;
|
|
4850
|
+
this.getStorage().setItem(this.TAROBASE_SESSION_STORAGE_KEY, JSON.stringify({
|
|
4851
|
+
address,
|
|
4852
|
+
accessToken,
|
|
4853
|
+
idToken,
|
|
4854
|
+
refreshToken,
|
|
4855
|
+
appId: currentAppId,
|
|
4856
|
+
}));
|
|
4857
|
+
}
|
|
4858
|
+
/* ------------------------------------------------------------------ */
|
|
4859
|
+
/* GET */
|
|
4860
|
+
/* ------------------------------------------------------------------ */
|
|
4861
|
+
static async getSession() {
|
|
4862
|
+
const session = this.getStorage().getItem(this.TAROBASE_SESSION_STORAGE_KEY);
|
|
4863
|
+
if (!session)
|
|
4864
|
+
return null;
|
|
4865
|
+
const sessionObj = JSON.parse(session);
|
|
4866
|
+
/* ---------- validate app-id ---------- */
|
|
4867
|
+
const config = await getConfig();
|
|
4868
|
+
if (sessionObj.appId && sessionObj.appId !== config.appId) {
|
|
4869
|
+
this.clearSession();
|
|
4870
|
+
return null;
|
|
4871
|
+
}
|
|
4872
|
+
/* ---------- check JWT expiration ---------- */
|
|
4873
|
+
try {
|
|
4874
|
+
const { accessToken } = sessionObj;
|
|
4875
|
+
const { exp } = JSON.parse(this.decodeBase64Url(accessToken.split(".")[1]));
|
|
4876
|
+
if (Date.now() > exp * 1000) {
|
|
4877
|
+
const { refreshToken } = sessionObj;
|
|
4878
|
+
if (!refreshToken)
|
|
4879
|
+
return null;
|
|
4880
|
+
const refreshed = await refreshSession(refreshToken);
|
|
4881
|
+
if ((refreshed === null || refreshed === void 0 ? void 0 : refreshed.idToken) && (refreshed === null || refreshed === void 0 ? void 0 : refreshed.accessToken)) {
|
|
4882
|
+
await this.updateIdTokenAndAccessToken(refreshed.idToken, refreshed.accessToken);
|
|
4883
|
+
const newSession = this.getStorage().getItem(this.TAROBASE_SESSION_STORAGE_KEY);
|
|
4884
|
+
if (!newSession)
|
|
4885
|
+
return null;
|
|
4886
|
+
const newObj = JSON.parse(newSession);
|
|
4887
|
+
return { address: newObj.address, session: newObj };
|
|
4888
|
+
}
|
|
4889
|
+
// Refresh failed — clear stale session to prevent retry loops
|
|
4890
|
+
this.clearSession();
|
|
4891
|
+
return null;
|
|
4892
|
+
}
|
|
4893
|
+
}
|
|
4894
|
+
catch (err) {
|
|
4895
|
+
// Token decode or refresh failed — clear stale session to prevent retry loops
|
|
4896
|
+
this.clearSession();
|
|
4897
|
+
return null;
|
|
4898
|
+
}
|
|
4899
|
+
return { address: sessionObj.address, session: sessionObj };
|
|
4900
|
+
}
|
|
4901
|
+
/* ------------------------------------------------------------------ */
|
|
4902
|
+
/* CLEAR */
|
|
4903
|
+
/* ------------------------------------------------------------------ */
|
|
4904
|
+
static clearSession() {
|
|
4905
|
+
this.getStorage().removeItem(this.TAROBASE_SESSION_STORAGE_KEY);
|
|
4906
|
+
}
|
|
4907
|
+
/* ------------------------------------------------------------------ */
|
|
4908
|
+
/* IS-AUTH */
|
|
4909
|
+
/* ------------------------------------------------------------------ */
|
|
4910
|
+
static isAuthenticated() {
|
|
4911
|
+
return !!this.getStorage().getItem(this.TAROBASE_SESSION_STORAGE_KEY);
|
|
4912
|
+
}
|
|
4913
|
+
/* ------------------------------------------------------------------ */
|
|
4914
|
+
/* TOKEN HELPERS */
|
|
4915
|
+
/* ------------------------------------------------------------------ */
|
|
4916
|
+
static getIdToken() {
|
|
4917
|
+
try {
|
|
4918
|
+
const session = this.getStorage().getItem(this.TAROBASE_SESSION_STORAGE_KEY);
|
|
4919
|
+
return session ? JSON.parse(session).idToken : null;
|
|
4920
|
+
}
|
|
4921
|
+
catch (_a) {
|
|
4922
|
+
return null;
|
|
4923
|
+
}
|
|
4924
|
+
}
|
|
4925
|
+
static getRefreshToken() {
|
|
4926
|
+
try {
|
|
4927
|
+
const session = this.getStorage().getItem(this.TAROBASE_SESSION_STORAGE_KEY);
|
|
4928
|
+
return session ? JSON.parse(session).refreshToken : null;
|
|
4929
|
+
}
|
|
4930
|
+
catch (_a) {
|
|
4931
|
+
return null;
|
|
4932
|
+
}
|
|
4933
|
+
}
|
|
4934
|
+
/* ------------------------------------------------------------------ */
|
|
4935
|
+
/* UPDATE TOKENS */
|
|
4936
|
+
/* ------------------------------------------------------------------ */
|
|
4937
|
+
static async updateIdTokenAndAccessToken(idToken, accessToken) {
|
|
4938
|
+
var _a;
|
|
4939
|
+
const session = this.getStorage().getItem(this.TAROBASE_SESSION_STORAGE_KEY);
|
|
4940
|
+
if (!session)
|
|
4941
|
+
return;
|
|
4942
|
+
const sessionObj = JSON.parse(session);
|
|
4943
|
+
/* ---------- app-id guard ---------- */
|
|
4944
|
+
const config = await getConfig();
|
|
4945
|
+
if (sessionObj.appId && sessionObj.appId !== config.appId) {
|
|
4946
|
+
this.clearSession();
|
|
4947
|
+
return;
|
|
4948
|
+
}
|
|
4949
|
+
sessionObj.idToken = idToken;
|
|
4950
|
+
sessionObj.accessToken = accessToken;
|
|
4951
|
+
(_a = sessionObj.appId) !== null && _a !== void 0 ? _a : (sessionObj.appId = config.appId);
|
|
4952
|
+
this.getStorage().setItem(this.TAROBASE_SESSION_STORAGE_KEY, JSON.stringify(sessionObj));
|
|
4953
|
+
}
|
|
4954
|
+
}
|
|
4955
|
+
ReactNativeSessionManager.TAROBASE_SESSION_STORAGE_KEY = "tarobase_session_storage";
|
|
4956
|
+
|
|
4957
|
+
export { InsufficientBalanceError, ReactNativeSessionManager, ServerSessionManager, WebSessionManager, aggregate, buildSetDocumentsTransaction, clearCache, closeAllSubscriptions, convertRemainingAccounts, count, createSessionWithPrivy, createSessionWithSignature, genAuthNonce, genSolanaMessage, get, getCachedData, getConfig, getFiles, getIdToken, init, reconnectWithNewAuth, refreshSession, runExpression, runExpressionMany, runQuery, runQueryMany, set, setFile, setMany, signAndSubmitTransaction, signMessage, signSessionCreateMessage, signTransaction, subscribe };
|
|
4743
4958
|
//# sourceMappingURL=index.mjs.map
|