@pooflabs/core 0.0.39 → 0.0.41
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 +245 -15
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +245 -16
- package/dist/index.mjs.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/utils/core-platform.d.ts +16 -0
- package/dist/utils/rn-session-manager.d.ts +73 -0
- package/dist/utils/sol/sol-utils.d.ts +1 -1
- 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)
|
|
@@ -2939,7 +2957,7 @@ function convertRemainingAccounts(remainingAccounts) {
|
|
|
2939
2957
|
// ─────────────────────────────────────────────────────────────
|
|
2940
2958
|
// Updated Transaction Builder: It now accepts a PublicKey for the payer
|
|
2941
2959
|
// ─────────────────────────────────────────────────────────────
|
|
2942
|
-
async function buildSetDocumentsTransaction(connection, idl, anchorProvider, payerPublicKey, args, remainingAccounts, lutKey, preInstructions, simulate) {
|
|
2960
|
+
async function buildSetDocumentsTransaction(connection, idl, anchorProvider, payerPublicKey, args, remainingAccounts, lutKey, preInstructions, simulate, additionalLutAddresses) {
|
|
2943
2961
|
const computeBudgetIx = ComputeBudgetProgram.setComputeUnitLimit({
|
|
2944
2962
|
units: 1400000,
|
|
2945
2963
|
});
|
|
@@ -2980,8 +2998,25 @@ async function buildSetDocumentsTransaction(connection, idl, anchorProvider, pay
|
|
|
2980
2998
|
tx.feePayer = payerPublicKey;
|
|
2981
2999
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed");
|
|
2982
3000
|
tx.recentBlockhash = blockhash;
|
|
2983
|
-
|
|
2984
|
-
|
|
3001
|
+
// Resolve LUTs: additionalLutAddresses (when present) is the authoritative set.
|
|
3002
|
+
// Falls back to lutKey alone for backwards compatibility.
|
|
3003
|
+
const lookupTables = [];
|
|
3004
|
+
const isSurfnet = anchorProvider.connection.rpcEndpoint == "https://surfpool.fly.dev";
|
|
3005
|
+
if (additionalLutAddresses && additionalLutAddresses.length > 0) {
|
|
3006
|
+
const results = await Promise.all(additionalLutAddresses.map(addr => connection.getAddressLookupTable(new PublicKey(addr)).catch(() => null)));
|
|
3007
|
+
for (const result of results) {
|
|
3008
|
+
if (result === null || result === void 0 ? void 0 : result.value) {
|
|
3009
|
+
lookupTables.push(result.value);
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
3012
|
+
}
|
|
3013
|
+
else if (lutKey != null) {
|
|
3014
|
+
const { value: table } = await connection.getAddressLookupTable(new PublicKey(lutKey));
|
|
3015
|
+
if (!table)
|
|
3016
|
+
throw new Error('LUT not found after creation/extend');
|
|
3017
|
+
lookupTables.push(table);
|
|
3018
|
+
}
|
|
3019
|
+
if (lookupTables.length === 0) {
|
|
2985
3020
|
const computeUnits = isSurfnet ? 1400000 : await getSimulationComputeUnits(connection, tx.instructions, payerPublicKey, []);
|
|
2986
3021
|
const computeBudgetIxOptimized = ComputeBudgetProgram.setComputeUnitLimit({
|
|
2987
3022
|
units: computeUnits ? computeUnits * 1.2 : 1400000,
|
|
@@ -2989,11 +3024,7 @@ async function buildSetDocumentsTransaction(connection, idl, anchorProvider, pay
|
|
|
2989
3024
|
tx.instructions[0] = computeBudgetIxOptimized;
|
|
2990
3025
|
return { tx, blockhash, lastValidBlockHeight };
|
|
2991
3026
|
}
|
|
2992
|
-
const
|
|
2993
|
-
if (!table)
|
|
2994
|
-
throw new Error('LUT not found after creation/extend');
|
|
2995
|
-
const isSurfnet = anchorProvider.connection.rpcEndpoint == "https://surfpool.fly.dev";
|
|
2996
|
-
const computeUnits = isSurfnet ? 1400000 : await getSimulationComputeUnits(connection, tx.instructions, payerPublicKey, [table]);
|
|
3027
|
+
const computeUnits = isSurfnet ? 1400000 : await getSimulationComputeUnits(connection, tx.instructions, payerPublicKey, lookupTables);
|
|
2997
3028
|
const computeBudgetIxOptimized = ComputeBudgetProgram.setComputeUnitLimit({
|
|
2998
3029
|
units: computeUnits ? computeUnits * 1.2 : 1400000,
|
|
2999
3030
|
}); // 20% buffer
|
|
@@ -3002,7 +3033,7 @@ async function buildSetDocumentsTransaction(connection, idl, anchorProvider, pay
|
|
|
3002
3033
|
payerKey: payerPublicKey,
|
|
3003
3034
|
recentBlockhash: blockhash,
|
|
3004
3035
|
instructions: tx.instructions,
|
|
3005
|
-
}).compileToV0Message(
|
|
3036
|
+
}).compileToV0Message(lookupTables);
|
|
3006
3037
|
const vTx = new anchor.web3.VersionedTransaction(msgV0);
|
|
3007
3038
|
return { tx: vTx, blockhash, lastValidBlockHeight };
|
|
3008
3039
|
}
|
|
@@ -3119,6 +3150,41 @@ var serverSessionManager = /*#__PURE__*/Object.freeze({
|
|
|
3119
3150
|
ServerSessionManager: ServerSessionManager
|
|
3120
3151
|
});
|
|
3121
3152
|
|
|
3153
|
+
/**
|
|
3154
|
+
* Safe base64 helpers for tarobase-core.
|
|
3155
|
+
*
|
|
3156
|
+
* Uses the global atob/btoa when available (browser, RN with polyfill),
|
|
3157
|
+
* falls back to the 'buffer' package (Node.js / SSR / RN without polyfill).
|
|
3158
|
+
*
|
|
3159
|
+
* These are used instead of bare `atob()`/`btoa()` so the core package
|
|
3160
|
+
* works in React Native without requiring the consumer to polyfill globals.
|
|
3161
|
+
*/
|
|
3162
|
+
function safeAtob(input) {
|
|
3163
|
+
if (typeof globalThis.atob === 'function') {
|
|
3164
|
+
return globalThis.atob(input);
|
|
3165
|
+
}
|
|
3166
|
+
return bufferExports.Buffer.from(input, 'base64').toString('binary');
|
|
3167
|
+
}
|
|
3168
|
+
function safeBtoa(input) {
|
|
3169
|
+
if (typeof globalThis.btoa === 'function') {
|
|
3170
|
+
return globalThis.btoa(input);
|
|
3171
|
+
}
|
|
3172
|
+
return bufferExports.Buffer.from(input, 'binary').toString('base64');
|
|
3173
|
+
}
|
|
3174
|
+
/**
|
|
3175
|
+
* Decode a base64url-encoded string (used by JWT payloads).
|
|
3176
|
+
* Normalises base64url → standard base64 before decoding.
|
|
3177
|
+
*/
|
|
3178
|
+
function decodeBase64Url(input) {
|
|
3179
|
+
let b64 = input.replace(/-/g, '+').replace(/_/g, '/');
|
|
3180
|
+
const pad = b64.length % 4;
|
|
3181
|
+
if (pad === 2)
|
|
3182
|
+
b64 += '==';
|
|
3183
|
+
else if (pad === 3)
|
|
3184
|
+
b64 += '=';
|
|
3185
|
+
return safeAtob(b64);
|
|
3186
|
+
}
|
|
3187
|
+
|
|
3122
3188
|
async function createBearerToken(isServer) {
|
|
3123
3189
|
if (isServer) {
|
|
3124
3190
|
const sessionMgr = ServerSessionManager.instance;
|
|
@@ -3618,7 +3684,7 @@ async function get(path, opts = {}) {
|
|
|
3618
3684
|
}
|
|
3619
3685
|
else {
|
|
3620
3686
|
const path = encodeURIComponent(normalizedPath);
|
|
3621
|
-
const promptQueryParam = (opts === null || opts === void 0 ? void 0 : opts.prompt) ? `&prompt=${
|
|
3687
|
+
const promptQueryParam = (opts === null || opts === void 0 ? void 0 : opts.prompt) ? `&prompt=${safeBtoa(opts.prompt)}` : "";
|
|
3622
3688
|
const apiPath = `items?path=${path}${promptQueryParam}${includeSubPathsParam}${shapeParam}${limitParam}${cursorParam}`;
|
|
3623
3689
|
response = await makeApiRequest('GET', apiPath, null, opts._overrides);
|
|
3624
3690
|
}
|
|
@@ -3851,6 +3917,7 @@ async function setMany(many, options) {
|
|
|
3851
3917
|
appId: config.appId,
|
|
3852
3918
|
txArgs: [solTransactionData],
|
|
3853
3919
|
lutKey: (_c = tx.lutAddress) !== null && _c !== void 0 ? _c : null,
|
|
3920
|
+
additionalLutAddresses: tx.additionalLutAddresses,
|
|
3854
3921
|
network: tx.network,
|
|
3855
3922
|
preInstructions: (_e = (_d = tx.preInstructions) === null || _d === void 0 ? void 0 : _d.map((ix) => {
|
|
3856
3923
|
var _a;
|
|
@@ -4073,7 +4140,7 @@ function getCacheKey(path, prompt, shape, limit, cursor) {
|
|
|
4073
4140
|
}
|
|
4074
4141
|
function isTokenExpired(token) {
|
|
4075
4142
|
try {
|
|
4076
|
-
const payload = JSON.parse(
|
|
4143
|
+
const payload = JSON.parse(decodeBase64Url(token.split('.')[1]));
|
|
4077
4144
|
const expirationTime = payload.exp * 1000;
|
|
4078
4145
|
const currentTime = Date.now();
|
|
4079
4146
|
return currentTime > (expirationTime - 60000); // 60 second buffer
|
|
@@ -4085,7 +4152,7 @@ function isTokenExpired(token) {
|
|
|
4085
4152
|
}
|
|
4086
4153
|
function getTokenExpirationTime(token) {
|
|
4087
4154
|
try {
|
|
4088
|
-
const payload = JSON.parse(
|
|
4155
|
+
const payload = JSON.parse(decodeBase64Url(token.split('.')[1]));
|
|
4089
4156
|
return payload.exp ? payload.exp * 1000 : null;
|
|
4090
4157
|
}
|
|
4091
4158
|
catch (_a) {
|
|
@@ -4413,7 +4480,7 @@ function sendSubscribe(connection, subscription) {
|
|
|
4413
4480
|
type: 'subscribe',
|
|
4414
4481
|
subscriptionId: subscription.subscriptionId,
|
|
4415
4482
|
path: subscription.path,
|
|
4416
|
-
prompt: subscription.prompt ?
|
|
4483
|
+
prompt: subscription.prompt ? safeBtoa(subscription.prompt) : undefined,
|
|
4417
4484
|
includeSubPaths: subscription.includeSubPaths,
|
|
4418
4485
|
shape: subscription.shape && Object.keys(subscription.shape).length > 0
|
|
4419
4486
|
? subscription.shape
|
|
@@ -4739,5 +4806,167 @@ async function reconnectWithNewAuth() {
|
|
|
4739
4806
|
return reconnectWithNewAuthV2();
|
|
4740
4807
|
}
|
|
4741
4808
|
|
|
4742
|
-
|
|
4809
|
+
let _config = null;
|
|
4810
|
+
class ReactNativeSessionManager {
|
|
4811
|
+
/**
|
|
4812
|
+
* Must be called once before any other method.
|
|
4813
|
+
*
|
|
4814
|
+
* ```ts
|
|
4815
|
+
* import { ReactNativeSessionManager } from '@pooflabs/core';
|
|
4816
|
+
* import { MMKV } from 'react-native-mmkv';
|
|
4817
|
+
* import { decode } from 'base-64';
|
|
4818
|
+
*
|
|
4819
|
+
* const mmkv = new MMKV();
|
|
4820
|
+
* ReactNativeSessionManager.configure({
|
|
4821
|
+
* storage: {
|
|
4822
|
+
* getItem: (k) => mmkv.getString(k) ?? null,
|
|
4823
|
+
* setItem: (k, v) => mmkv.set(k, v),
|
|
4824
|
+
* removeItem: (k) => mmkv.delete(k),
|
|
4825
|
+
* },
|
|
4826
|
+
* atob: decode,
|
|
4827
|
+
* });
|
|
4828
|
+
* ```
|
|
4829
|
+
*/
|
|
4830
|
+
static configure(cfg) {
|
|
4831
|
+
_config = cfg;
|
|
4832
|
+
}
|
|
4833
|
+
static getStorage() {
|
|
4834
|
+
if (!_config) {
|
|
4835
|
+
throw new Error("ReactNativeSessionManager.configure() must be called before using session methods.");
|
|
4836
|
+
}
|
|
4837
|
+
return _config.storage;
|
|
4838
|
+
}
|
|
4839
|
+
static decodeBase64(input) {
|
|
4840
|
+
if (!_config) {
|
|
4841
|
+
throw new Error("ReactNativeSessionManager.configure() must be called before using session methods.");
|
|
4842
|
+
}
|
|
4843
|
+
return _config.atob(input);
|
|
4844
|
+
}
|
|
4845
|
+
/**
|
|
4846
|
+
* Decode a base64url-encoded string (used by JWT payloads).
|
|
4847
|
+
* Normalises base64url → standard base64 before decoding.
|
|
4848
|
+
*/
|
|
4849
|
+
static decodeBase64Url(input) {
|
|
4850
|
+
let b64 = input.replace(/-/g, '+').replace(/_/g, '/');
|
|
4851
|
+
const pad = b64.length % 4;
|
|
4852
|
+
if (pad === 2)
|
|
4853
|
+
b64 += '==';
|
|
4854
|
+
else if (pad === 3)
|
|
4855
|
+
b64 += '=';
|
|
4856
|
+
return this.decodeBase64(b64);
|
|
4857
|
+
}
|
|
4858
|
+
/* ------------------------------------------------------------------ */
|
|
4859
|
+
/* STORE */
|
|
4860
|
+
/* ------------------------------------------------------------------ */
|
|
4861
|
+
static async storeSession(address, accessToken, idToken, refreshToken) {
|
|
4862
|
+
const config = await getConfig();
|
|
4863
|
+
const currentAppId = config.appId;
|
|
4864
|
+
this.getStorage().setItem(this.TAROBASE_SESSION_STORAGE_KEY, JSON.stringify({
|
|
4865
|
+
address,
|
|
4866
|
+
accessToken,
|
|
4867
|
+
idToken,
|
|
4868
|
+
refreshToken,
|
|
4869
|
+
appId: currentAppId,
|
|
4870
|
+
}));
|
|
4871
|
+
}
|
|
4872
|
+
/* ------------------------------------------------------------------ */
|
|
4873
|
+
/* GET */
|
|
4874
|
+
/* ------------------------------------------------------------------ */
|
|
4875
|
+
static async getSession() {
|
|
4876
|
+
const session = this.getStorage().getItem(this.TAROBASE_SESSION_STORAGE_KEY);
|
|
4877
|
+
if (!session)
|
|
4878
|
+
return null;
|
|
4879
|
+
const sessionObj = JSON.parse(session);
|
|
4880
|
+
/* ---------- validate app-id ---------- */
|
|
4881
|
+
const config = await getConfig();
|
|
4882
|
+
if (sessionObj.appId && sessionObj.appId !== config.appId) {
|
|
4883
|
+
this.clearSession();
|
|
4884
|
+
return null;
|
|
4885
|
+
}
|
|
4886
|
+
/* ---------- check JWT expiration ---------- */
|
|
4887
|
+
try {
|
|
4888
|
+
const { accessToken } = sessionObj;
|
|
4889
|
+
const { exp } = JSON.parse(this.decodeBase64Url(accessToken.split(".")[1]));
|
|
4890
|
+
if (Date.now() > exp * 1000) {
|
|
4891
|
+
const { refreshToken } = sessionObj;
|
|
4892
|
+
if (!refreshToken)
|
|
4893
|
+
return null;
|
|
4894
|
+
const refreshed = await refreshSession(refreshToken);
|
|
4895
|
+
if ((refreshed === null || refreshed === void 0 ? void 0 : refreshed.idToken) && (refreshed === null || refreshed === void 0 ? void 0 : refreshed.accessToken)) {
|
|
4896
|
+
await this.updateIdTokenAndAccessToken(refreshed.idToken, refreshed.accessToken);
|
|
4897
|
+
const newSession = this.getStorage().getItem(this.TAROBASE_SESSION_STORAGE_KEY);
|
|
4898
|
+
if (!newSession)
|
|
4899
|
+
return null;
|
|
4900
|
+
const newObj = JSON.parse(newSession);
|
|
4901
|
+
return { address: newObj.address, session: newObj };
|
|
4902
|
+
}
|
|
4903
|
+
// Refresh failed — clear stale session to prevent retry loops
|
|
4904
|
+
this.clearSession();
|
|
4905
|
+
return null;
|
|
4906
|
+
}
|
|
4907
|
+
}
|
|
4908
|
+
catch (err) {
|
|
4909
|
+
// Token decode or refresh failed — clear stale session to prevent retry loops
|
|
4910
|
+
this.clearSession();
|
|
4911
|
+
return null;
|
|
4912
|
+
}
|
|
4913
|
+
return { address: sessionObj.address, session: sessionObj };
|
|
4914
|
+
}
|
|
4915
|
+
/* ------------------------------------------------------------------ */
|
|
4916
|
+
/* CLEAR */
|
|
4917
|
+
/* ------------------------------------------------------------------ */
|
|
4918
|
+
static clearSession() {
|
|
4919
|
+
this.getStorage().removeItem(this.TAROBASE_SESSION_STORAGE_KEY);
|
|
4920
|
+
}
|
|
4921
|
+
/* ------------------------------------------------------------------ */
|
|
4922
|
+
/* IS-AUTH */
|
|
4923
|
+
/* ------------------------------------------------------------------ */
|
|
4924
|
+
static isAuthenticated() {
|
|
4925
|
+
return !!this.getStorage().getItem(this.TAROBASE_SESSION_STORAGE_KEY);
|
|
4926
|
+
}
|
|
4927
|
+
/* ------------------------------------------------------------------ */
|
|
4928
|
+
/* TOKEN HELPERS */
|
|
4929
|
+
/* ------------------------------------------------------------------ */
|
|
4930
|
+
static getIdToken() {
|
|
4931
|
+
try {
|
|
4932
|
+
const session = this.getStorage().getItem(this.TAROBASE_SESSION_STORAGE_KEY);
|
|
4933
|
+
return session ? JSON.parse(session).idToken : null;
|
|
4934
|
+
}
|
|
4935
|
+
catch (_a) {
|
|
4936
|
+
return null;
|
|
4937
|
+
}
|
|
4938
|
+
}
|
|
4939
|
+
static getRefreshToken() {
|
|
4940
|
+
try {
|
|
4941
|
+
const session = this.getStorage().getItem(this.TAROBASE_SESSION_STORAGE_KEY);
|
|
4942
|
+
return session ? JSON.parse(session).refreshToken : null;
|
|
4943
|
+
}
|
|
4944
|
+
catch (_a) {
|
|
4945
|
+
return null;
|
|
4946
|
+
}
|
|
4947
|
+
}
|
|
4948
|
+
/* ------------------------------------------------------------------ */
|
|
4949
|
+
/* UPDATE TOKENS */
|
|
4950
|
+
/* ------------------------------------------------------------------ */
|
|
4951
|
+
static async updateIdTokenAndAccessToken(idToken, accessToken) {
|
|
4952
|
+
var _a;
|
|
4953
|
+
const session = this.getStorage().getItem(this.TAROBASE_SESSION_STORAGE_KEY);
|
|
4954
|
+
if (!session)
|
|
4955
|
+
return;
|
|
4956
|
+
const sessionObj = JSON.parse(session);
|
|
4957
|
+
/* ---------- app-id guard ---------- */
|
|
4958
|
+
const config = await getConfig();
|
|
4959
|
+
if (sessionObj.appId && sessionObj.appId !== config.appId) {
|
|
4960
|
+
this.clearSession();
|
|
4961
|
+
return;
|
|
4962
|
+
}
|
|
4963
|
+
sessionObj.idToken = idToken;
|
|
4964
|
+
sessionObj.accessToken = accessToken;
|
|
4965
|
+
(_a = sessionObj.appId) !== null && _a !== void 0 ? _a : (sessionObj.appId = config.appId);
|
|
4966
|
+
this.getStorage().setItem(this.TAROBASE_SESSION_STORAGE_KEY, JSON.stringify(sessionObj));
|
|
4967
|
+
}
|
|
4968
|
+
}
|
|
4969
|
+
ReactNativeSessionManager.TAROBASE_SESSION_STORAGE_KEY = "tarobase_session_storage";
|
|
4970
|
+
|
|
4971
|
+
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
4972
|
//# sourceMappingURL=index.mjs.map
|