@tuwaio/pulsar-core 0.10.0 → 0.10.2

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 CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
  - **Transaction store:** `createPulsarStore` returns a vanilla Zustand store. Its `executeTxAction` validates the metadata, sets `initialTx` for immediate UI feedback, checks the wallet's chain, runs the `beforeTxProcess` preflight, calls your `actionFunction` to sign and submit, adds the transaction to `transactionsPool` and starts its tracker.
13
13
  - **Chain adapters:** pass one adapter or an array. Each transaction goes to the adapter whose `key` matches its `adapter` (the first adapter when none matches). Adapters implement the `TxAdapter` contract, so other chains can be added.
14
- - **Persistence and resume:** the pool is saved to `localStorage` (see Browser Storage below). After a reload, `initializeTransactionsPool` restarts the trackers of pending transactions. The pool keeps at most `maxTransactions` (default 50) and evicts the oldest one.
14
+ - **Persistence and resume:** the pool is saved to `localStorage` (see Browser Storage below). After a reload, `initializeTransactionsPool` restarts the trackers of pending transactions. The pool keeps at most `maxTransactions` (default 50) and evicts the oldest one; a finished transaction is dropped `retentionDays` (default 30) after it finished.
15
15
  - **Metadata safety:** each `title` string is limited to 100 characters, each `description` string to 300 and the JSON of `payload` to 10 KB, and strings must not contain executable-like patterns (`eval(`, `Function(`, `setTimeout`/`setInterval` with a string, `javascript:`). Invalid metadata throws `PulsarTransactionValidationError` before anything runs; invalid restored or remote transactions are dropped. This is a defensive gate, not a replacement for escaping output in your UI.
16
16
  - **Remote sync:** `onRemoteCreate` sends every new transaction to your backend (for example Quasar) in the background, without its API keys, retries unconfirmed syncs later, and never delays or blocks tracking. `injectExternalPendingTxs` and `createTxInMemoryStore` bring the remote history back into the app; both drop transactions that fail validation.
17
17
  - **Selectors and React binding:** `selectAllTransactions`, `selectPendingTransactions`, `selectTxByKey` and the `…ByActiveWallet` variants; `createBoundedUseStore` turns the store into a typed React hook.
@@ -137,7 +137,7 @@ To show the remote history, `createTxInMemoryStore` merges the pages returned by
137
137
 
138
138
  - The state is written on every change: when a transaction is added, updated by its tracker or removed. `initialTx`, the transaction being signed, is neither saved nor restored, so a reload during signing leaves no stale signing state (pass your own `partialize` and `merge` to change that).
139
139
  - In the browser the saved state is restored synchronously when the store is created, so the first client render already has the pool. Server rendering starts with an empty pool: render transaction lists on the client only. Where `localStorage` is unavailable, nothing is read or written.
140
- - Nothing expires on its own. Transactions leave the pool only through the `maxTransactions` eviction or `removeTxFromPool`: the built-in trackers keep failed transactions as `Failed`. `store.persist.clearStorage()` deletes the saved state.
140
+ - A finished transaction (including a `Failed` one) is dropped `retentionDays` after its `finishedTimestamp` (or its `localTimestamp` when it has none), when the saved state is restored and when a transaction is added; the default is 30 days, and `retentionDays: null` keeps finished transactions without a term. Pending transactions stay until they finish. Transactions also leave the pool through the `maxTransactions` eviction and `removeTxFromPool`. `store.persist.clearStorage()` deletes the saved state.
141
141
  - Everything in a transaction is saved, including `payload` and, for ERC-4337, `bundlerUrl` and `pimlicoApiKey` (needed to resume tracking after a reload; a Pimlico key used in the browser is public anyway). Do not put secrets in `payload`.
142
142
  - `createTxInMemoryStore` keeps its state in memory only.
143
143
 
package/dist/index.d.mts CHANGED
@@ -344,6 +344,13 @@ type PulsarAdapter<T extends Transaction> = OrbitGenericAdapter<TxAdapter<T>> &
344
344
  beforeTxProcess?: BeforeTxProcess;
345
345
  /** Maximum number of transactions in the pool. When it is full, the oldest one (by `localTimestamp`) is evicted. Defaults to 50. */
346
346
  maxTransactions?: number;
347
+ /**
348
+ * Days a finished transaction stays in the pool, counted from its `finishedTimestamp` (or `localTimestamp` when it
349
+ * has none). Expired ones are dropped when the saved state is restored and when a transaction is added; pending
350
+ * transactions stay until they finish. `null` keeps finished transactions until `maxTransactions` evicts them.
351
+ * Defaults to 30.
352
+ */
353
+ retentionDays?: number | null;
347
354
  /** @deprecated Gelato relay is deprecated. Gelato API key used to track `TransactionTracker.Gelato` transactions. */
348
355
  gelatoApiKey?: string;
349
356
  /**
@@ -676,11 +683,13 @@ type ITxInMemoryStoreParameters<T extends Transaction> = {
676
683
  * @param params - The slice options.
677
684
  * @param params.maxTransactions - Maximum number of transactions in the pool; `addTxToPool` evicts the oldest one
678
685
  * (by `localTimestamp`) when the pool is full.
686
+ * @param params.retentionDays - Days a finished transaction stays in the pool; `addTxToPool` drops the expired ones
687
+ * first. `null` keeps them without a term. Defaults to 30.
679
688
  * @param params.onRemoteCreate - Optional remote sync callback, called in the background by `addTxToPool` (see
680
689
  * `SyncCallbacks`).
681
690
  * @returns A slice creator for Zustand's `create` / `createStore`.
682
691
  */
683
- declare function initializeTxTrackingStore<T extends Transaction>({ maxTransactions, onRemoteCreate, }: Pick<PulsarAdapter<T>, 'onRemoteCreate'> & {
692
+ declare function initializeTxTrackingStore<T extends Transaction>({ maxTransactions, retentionDays, onRemoteCreate, }: Pick<PulsarAdapter<T>, 'onRemoteCreate' | 'retentionDays'> & {
684
693
  maxTransactions: number;
685
694
  }): StoreSlice<IInitializeTxTrackingStore<T>>;
686
695
 
@@ -763,7 +772,8 @@ declare function createTxInMemoryStore<T extends Transaction>({ localTransaction
763
772
  * `createBoundedUseStore`) that runs transactions through chain adapters and tracks them in the background.
764
773
  *
765
774
  * Side effects: the state is saved with Zustand's `persist` middleware under the key `name`, by default in
766
- * `localStorage`, on every change: `transactionsPool`, `lastAddedTxKey` and `unsyncedTxKeys`. `initialTx` is neither
775
+ * `localStorage`, on every change: `transactionsPool`, `lastAddedTxKey` and `unsyncedTxKeys`. A finished transaction
776
+ * is kept for `retentionDays` (30 by default) and at most `maxTransactions` are kept. `initialTx` is neither
767
777
  * saved nor restored (pass your own `partialize` and `merge` to change that). In the browser the saved state is
768
778
  * restored synchronously when the store is created. Where
769
779
  * `localStorage` is not available (server rendering), nothing is read or written and Zustand logs a warning on
@@ -774,6 +784,9 @@ declare function createTxInMemoryStore<T extends Transaction>({ localTransaction
774
784
  * @param params.adapter - A chain adapter, or an array of adapters, such as `pulsarEvmAdapter` from
775
785
  * `@tuwaio/pulsar-evm` or `pulsarSolanaAdapter` from `@tuwaio/pulsar-solana`.
776
786
  * @param params.maxTransactions - Maximum number of transactions in the pool. Defaults to 50.
787
+ * @param params.retentionDays - Days a finished transaction stays in the pool, from its `finishedTimestamp`: expired
788
+ * ones are dropped when the saved state is restored and when a transaction is added. `null` keeps them without a
789
+ * term. Defaults to 30.
777
790
  * @param params.onRemoteCreate - Remote sync callback (see `SyncCallbacks`).
778
791
  * @param params.gelatoApiKey - Deprecated Gelato API key, passed to the trackers.
779
792
  * @param params.beforeTxProcess - Global preflight callback (see `BeforeTxProcess`).
@@ -792,7 +805,7 @@ declare function createTxInMemoryStore<T extends Transaction>({ localTransaction
792
805
  * });
793
806
  * ```
794
807
  */
795
- declare function createPulsarStore<T extends Transaction>({ adapter, maxTransactions, onRemoteCreate, gelatoApiKey, beforeTxProcess, abortOnTxError, ...options }: PulsarAdapter<T> & PersistOptions<ITxTrackingStore<T>>): Omit<zustand.StoreApi<ITxTrackingStore<T>>, "setState" | "persist"> & {
808
+ declare function createPulsarStore<T extends Transaction>({ adapter, maxTransactions, retentionDays, onRemoteCreate, gelatoApiKey, beforeTxProcess, abortOnTxError, ...options }: PulsarAdapter<T> & PersistOptions<ITxTrackingStore<T>>): Omit<zustand.StoreApi<ITxTrackingStore<T>>, "setState" | "persist"> & {
796
809
  setState(partial: ITxTrackingStore<T> | Partial<ITxTrackingStore<T>> | ((state: ITxTrackingStore<T>) => ITxTrackingStore<T> | Partial<ITxTrackingStore<T>>), replace?: false | undefined): unknown;
797
810
  setState(state: ITxTrackingStore<T> | ((state: ITxTrackingStore<T>) => ITxTrackingStore<T>), replace: true): unknown;
798
811
  persist: {
@@ -1046,4 +1059,5 @@ declare function validateInitialTransactionParams(params: Omit<InitialTransactio
1046
1059
  */
1047
1060
  declare function validateTransaction<T extends Transaction>(tx: T): void;
1048
1061
 
1049
- export { type ActionTxKey, type BaseTransaction, type BeforeTxProcess, type CheckTxTracker, type EvmTransaction, type ExtractState, type IInitializeTxTrackingStore, type ITxInMemoryStore, type ITxInMemoryStoreParameters, type ITxTrackingStore, type InitialTransaction, type InitialTransactionParams, MAX_TRANSACTION_DESCRIPTION_LENGTH, MAX_TRANSACTION_PAYLOAD_BYTES, MAX_TRANSACTION_TITLE_LENGTH, type PollingFetcherParams, type PollingTrackerConfig, type PulsarAdapter, PulsarTransactionValidationError, type SolanaTransaction, type StarknetTransaction, type StoreSlice, type SyncCallbacks, type TrackerCallbacks, type Transaction, type TransactionPool, TransactionStatus, TransactionTracker, type TxAdapter, type TxInMemoryPagination, type UpdatableTransactionFields, createBoundedUseStore, createPulsarStore, createTxInMemoryStore, createTxUpdater, initializePollingTracker, initializeTxTrackingStore, selectAllTransactions, selectAllTransactionsByActiveWallet, selectPendingTransactions, selectPendingTransactionsByActiveWallet, selectTxByKey, validateInitialTransactionParams, validateTransaction };
1062
+ export { MAX_TRANSACTION_DESCRIPTION_LENGTH, MAX_TRANSACTION_PAYLOAD_BYTES, MAX_TRANSACTION_TITLE_LENGTH, PulsarTransactionValidationError, TransactionStatus, TransactionTracker, createBoundedUseStore, createPulsarStore, createTxInMemoryStore, createTxUpdater, initializePollingTracker, initializeTxTrackingStore, selectAllTransactions, selectAllTransactionsByActiveWallet, selectPendingTransactions, selectPendingTransactionsByActiveWallet, selectTxByKey, validateInitialTransactionParams, validateTransaction };
1063
+ export type { ActionTxKey, BaseTransaction, BeforeTxProcess, CheckTxTracker, EvmTransaction, ExtractState, IInitializeTxTrackingStore, ITxInMemoryStore, ITxInMemoryStoreParameters, ITxTrackingStore, InitialTransaction, InitialTransactionParams, PollingFetcherParams, PollingTrackerConfig, PulsarAdapter, SolanaTransaction, StarknetTransaction, StoreSlice, SyncCallbacks, TrackerCallbacks, Transaction, TransactionPool, TxAdapter, TxInMemoryPagination, UpdatableTransactionFields };
package/dist/index.d.ts CHANGED
@@ -344,6 +344,13 @@ type PulsarAdapter<T extends Transaction> = OrbitGenericAdapter<TxAdapter<T>> &
344
344
  beforeTxProcess?: BeforeTxProcess;
345
345
  /** Maximum number of transactions in the pool. When it is full, the oldest one (by `localTimestamp`) is evicted. Defaults to 50. */
346
346
  maxTransactions?: number;
347
+ /**
348
+ * Days a finished transaction stays in the pool, counted from its `finishedTimestamp` (or `localTimestamp` when it
349
+ * has none). Expired ones are dropped when the saved state is restored and when a transaction is added; pending
350
+ * transactions stay until they finish. `null` keeps finished transactions until `maxTransactions` evicts them.
351
+ * Defaults to 30.
352
+ */
353
+ retentionDays?: number | null;
347
354
  /** @deprecated Gelato relay is deprecated. Gelato API key used to track `TransactionTracker.Gelato` transactions. */
348
355
  gelatoApiKey?: string;
349
356
  /**
@@ -676,11 +683,13 @@ type ITxInMemoryStoreParameters<T extends Transaction> = {
676
683
  * @param params - The slice options.
677
684
  * @param params.maxTransactions - Maximum number of transactions in the pool; `addTxToPool` evicts the oldest one
678
685
  * (by `localTimestamp`) when the pool is full.
686
+ * @param params.retentionDays - Days a finished transaction stays in the pool; `addTxToPool` drops the expired ones
687
+ * first. `null` keeps them without a term. Defaults to 30.
679
688
  * @param params.onRemoteCreate - Optional remote sync callback, called in the background by `addTxToPool` (see
680
689
  * `SyncCallbacks`).
681
690
  * @returns A slice creator for Zustand's `create` / `createStore`.
682
691
  */
683
- declare function initializeTxTrackingStore<T extends Transaction>({ maxTransactions, onRemoteCreate, }: Pick<PulsarAdapter<T>, 'onRemoteCreate'> & {
692
+ declare function initializeTxTrackingStore<T extends Transaction>({ maxTransactions, retentionDays, onRemoteCreate, }: Pick<PulsarAdapter<T>, 'onRemoteCreate' | 'retentionDays'> & {
684
693
  maxTransactions: number;
685
694
  }): StoreSlice<IInitializeTxTrackingStore<T>>;
686
695
 
@@ -763,7 +772,8 @@ declare function createTxInMemoryStore<T extends Transaction>({ localTransaction
763
772
  * `createBoundedUseStore`) that runs transactions through chain adapters and tracks them in the background.
764
773
  *
765
774
  * Side effects: the state is saved with Zustand's `persist` middleware under the key `name`, by default in
766
- * `localStorage`, on every change: `transactionsPool`, `lastAddedTxKey` and `unsyncedTxKeys`. `initialTx` is neither
775
+ * `localStorage`, on every change: `transactionsPool`, `lastAddedTxKey` and `unsyncedTxKeys`. A finished transaction
776
+ * is kept for `retentionDays` (30 by default) and at most `maxTransactions` are kept. `initialTx` is neither
767
777
  * saved nor restored (pass your own `partialize` and `merge` to change that). In the browser the saved state is
768
778
  * restored synchronously when the store is created. Where
769
779
  * `localStorage` is not available (server rendering), nothing is read or written and Zustand logs a warning on
@@ -774,6 +784,9 @@ declare function createTxInMemoryStore<T extends Transaction>({ localTransaction
774
784
  * @param params.adapter - A chain adapter, or an array of adapters, such as `pulsarEvmAdapter` from
775
785
  * `@tuwaio/pulsar-evm` or `pulsarSolanaAdapter` from `@tuwaio/pulsar-solana`.
776
786
  * @param params.maxTransactions - Maximum number of transactions in the pool. Defaults to 50.
787
+ * @param params.retentionDays - Days a finished transaction stays in the pool, from its `finishedTimestamp`: expired
788
+ * ones are dropped when the saved state is restored and when a transaction is added. `null` keeps them without a
789
+ * term. Defaults to 30.
777
790
  * @param params.onRemoteCreate - Remote sync callback (see `SyncCallbacks`).
778
791
  * @param params.gelatoApiKey - Deprecated Gelato API key, passed to the trackers.
779
792
  * @param params.beforeTxProcess - Global preflight callback (see `BeforeTxProcess`).
@@ -792,7 +805,7 @@ declare function createTxInMemoryStore<T extends Transaction>({ localTransaction
792
805
  * });
793
806
  * ```
794
807
  */
795
- declare function createPulsarStore<T extends Transaction>({ adapter, maxTransactions, onRemoteCreate, gelatoApiKey, beforeTxProcess, abortOnTxError, ...options }: PulsarAdapter<T> & PersistOptions<ITxTrackingStore<T>>): Omit<zustand.StoreApi<ITxTrackingStore<T>>, "setState" | "persist"> & {
808
+ declare function createPulsarStore<T extends Transaction>({ adapter, maxTransactions, retentionDays, onRemoteCreate, gelatoApiKey, beforeTxProcess, abortOnTxError, ...options }: PulsarAdapter<T> & PersistOptions<ITxTrackingStore<T>>): Omit<zustand.StoreApi<ITxTrackingStore<T>>, "setState" | "persist"> & {
796
809
  setState(partial: ITxTrackingStore<T> | Partial<ITxTrackingStore<T>> | ((state: ITxTrackingStore<T>) => ITxTrackingStore<T> | Partial<ITxTrackingStore<T>>), replace?: false | undefined): unknown;
797
810
  setState(state: ITxTrackingStore<T> | ((state: ITxTrackingStore<T>) => ITxTrackingStore<T>), replace: true): unknown;
798
811
  persist: {
@@ -1046,4 +1059,5 @@ declare function validateInitialTransactionParams(params: Omit<InitialTransactio
1046
1059
  */
1047
1060
  declare function validateTransaction<T extends Transaction>(tx: T): void;
1048
1061
 
1049
- export { type ActionTxKey, type BaseTransaction, type BeforeTxProcess, type CheckTxTracker, type EvmTransaction, type ExtractState, type IInitializeTxTrackingStore, type ITxInMemoryStore, type ITxInMemoryStoreParameters, type ITxTrackingStore, type InitialTransaction, type InitialTransactionParams, MAX_TRANSACTION_DESCRIPTION_LENGTH, MAX_TRANSACTION_PAYLOAD_BYTES, MAX_TRANSACTION_TITLE_LENGTH, type PollingFetcherParams, type PollingTrackerConfig, type PulsarAdapter, PulsarTransactionValidationError, type SolanaTransaction, type StarknetTransaction, type StoreSlice, type SyncCallbacks, type TrackerCallbacks, type Transaction, type TransactionPool, TransactionStatus, TransactionTracker, type TxAdapter, type TxInMemoryPagination, type UpdatableTransactionFields, createBoundedUseStore, createPulsarStore, createTxInMemoryStore, createTxUpdater, initializePollingTracker, initializeTxTrackingStore, selectAllTransactions, selectAllTransactionsByActiveWallet, selectPendingTransactions, selectPendingTransactionsByActiveWallet, selectTxByKey, validateInitialTransactionParams, validateTransaction };
1062
+ export { MAX_TRANSACTION_DESCRIPTION_LENGTH, MAX_TRANSACTION_PAYLOAD_BYTES, MAX_TRANSACTION_TITLE_LENGTH, PulsarTransactionValidationError, TransactionStatus, TransactionTracker, createBoundedUseStore, createPulsarStore, createTxInMemoryStore, createTxUpdater, initializePollingTracker, initializeTxTrackingStore, selectAllTransactions, selectAllTransactionsByActiveWallet, selectPendingTransactions, selectPendingTransactionsByActiveWallet, selectTxByKey, validateInitialTransactionParams, validateTransaction };
1063
+ export type { ActionTxKey, BaseTransaction, BeforeTxProcess, CheckTxTracker, EvmTransaction, ExtractState, IInitializeTxTrackingStore, ITxInMemoryStore, ITxInMemoryStoreParameters, ITxTrackingStore, InitialTransaction, InitialTransactionParams, PollingFetcherParams, PollingTrackerConfig, PulsarAdapter, SolanaTransaction, StarknetTransaction, StoreSlice, SyncCallbacks, TrackerCallbacks, Transaction, TransactionPool, TxAdapter, TxInMemoryPagination, UpdatableTransactionFields };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- 'use strict';var immer=require('immer'),vanilla=require('zustand/vanilla'),orbitCore=require('@tuwaio/orbit-core'),ce=require('dayjs'),middleware=require('zustand/middleware'),zustand=require('zustand');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var ce__default=/*#__PURE__*/_interopDefault(ce);var ee=(s=>(s.Ethereum="ethereum",s.Safe="safe",s.Gelato="gelato",s.Solana="solana",s.ERC4337="erc4337",s.EIP5792="eip5792",s))(ee||{}),K=(T=>(T.Failed="Failed",T.Success="Success",T.Replaced="Replaced",T))(K||{});var U=100,B=300,N=10*1024,ne=[/\beval\s*\(/i,/\bFunction\s*\(/,/\bset(?:Timeout|Interval)\s*\(\s*['"`]/i,/javascript\s*:/i],P=class extends Error{field;constructor(e,o){super(o),this.name="PulsarTransactionValidationError",this.field=e;}};function $(n){w({field:"title",value:n.title,maxLength:U}),w({field:"description",value:n.description,maxLength:B}),j(n.payload);}function S(n){w({field:"title",value:n.title,maxLength:U}),w({field:"description",value:n.description,maxLength:B}),j(n.payload);}function w({field:n,value:e,maxLength:o}){if(e===void 0)return;(Array.isArray(e)?e:[e]).forEach((d,p)=>{let s=Array.isArray(e)?`${n}[${p}]`:n;if(typeof d!="string")throw new P(s,`${s} must be a string.`);if(d.length>o)throw new P(s,`${s} must be ${o} characters or less.`);O(s,d);});}function j(n){if(n===void 0)return;let e;try{e=JSON.stringify(n);}catch{throw new P("payload","payload must be JSON-serializable.")}if(e===void 0)throw new P("payload","payload must be JSON-serializable.");if(new TextEncoder().encode(e).length>N)throw new P("payload",`payload must be ${N} bytes or less when serialized.`);_(n);}function _(n,e="payload"){if(typeof n=="string"){O(e,n);return}n===null||typeof n!="object"||Object.entries(n).forEach(([o,T])=>{let d=`${e}.${o}`;O(d,o),_(T,d);});}function O(n,e){if(ne.some(o=>o.test(e)))throw new P(n,`${n} contains a blocked executable-like pattern.`)}function te(n){let e={...n};return delete e.pimlicoApiKey,delete e.gelatoApiKey,e}function G({maxTransactions:n,onRemoteCreate:e}){let o=false,T=new Set;return (d,p)=>{let s=async(t,r)=>{let c=p().transactionsPool[t];if(!(!e||!c||T.has(t))){T.add(t);try{await e(te(c)),d(a=>immer.produce(a,i=>{let l=i.transactionsPool[t];l&&(l.syncStatus="synced"),i.unsyncedTxKeys&&delete i.unsyncedTxKeys[t];}));}catch(a){console.warn(r,a);}finally{T.delete(t);}}};return {transactionsPool:{},lastAddedTxKey:void 0,initialTx:void 0,unsyncedTxKeys:{},reconcileUnsyncedTransactions:async()=>{if(!e||o)return;let t=Object.keys(p().unsyncedTxKeys||{});if(t.length!==0){o=true;try{for(let r of t){if(!p().transactionsPool[r]){d(c=>immer.produce(c,a=>{a.unsyncedTxKeys&&delete a.unsyncedTxKeys[r];}));continue}await s(r,`[Pulsar] Failed to reconcile tx ${r}:`);}}finally{o=false;}}},addTxToPool:t=>{S(t);let r={...t,pending:true,...e&&{syncStatus:"pending-sync"}};return d(c=>immer.produce(c,a=>{if(a.lastAddedTxKey=t.txKey,t.txKey){if(e&&(a.unsyncedTxKeys||(a.unsyncedTxKeys={}),a.unsyncedTxKeys[t.txKey]=true),Object.keys(a.transactionsPool).length>=n){let l=Object.values(a.transactionsPool).sort((x,y)=>x.localTimestamp-y.localTimestamp);if(l.length>0){let x=l[0];delete a.transactionsPool[x.txKey];}}a.transactionsPool[t.txKey]=r;}})),e&&t.txKey&&s(t.txKey,"[Pulsar] onRemoteCreate failed, transaction queued for background sync:"),Promise.resolve()},updateTxParams:(t,r)=>{d(a=>immer.produce(a,i=>{let l=i.transactionsPool[t];l&&Object.assign(l,r);})),(r.status==="Success"||r.status==="Failed"||r.status==="Replaced")&&p().reconcileUnsyncedTransactions&&p().unsyncedTxKeys?.[t]&&p().reconcileUnsyncedTransactions().catch(a=>{console.error("[Pulsar] Terminal reconciliation failed:",a);});},removeTxFromPool:t=>{d(r=>immer.produce(r,c=>{delete c.transactionsPool[t];}));},closeTxTrackedModal:t=>{d(r=>immer.produce(r,c=>{if(t&&c.transactionsPool[t]){let a=c.transactionsPool[t];c.transactionsPool[t]={...a,isTrackedModalOpen:false};}c.initialTx=void 0;}));},getLastTxKey:()=>p().lastAddedTxKey}}}var D=n=>Object.values(n).sort((e,o)=>Number(e.localTimestamp)-Number(o.localTimestamp)),Ae=n=>D(n).filter(e=>e.pending),ve=(n,e)=>n[e],re=(n,e)=>D(n).filter(o=>o.from.toLowerCase()===e.toLowerCase()),Ie=(n,e)=>re(n,e).filter(o=>o.pending);var{produce:q}=new immer.Immer({autoFreeze:false}),ae=n=>n.filter(e=>{try{return S(e),!0}catch(o){return console.warn("[Pulsar] Skipped invalid transaction from history:",o),false}}),H=n=>n==="Success"||n==="Failed"||n==="Replaced",V=(n,e)=>{let o=n[e.txKey];if(o){if(H(o.status))return false;if(o.pending){if(H(e.status))return n[e.txKey]={...o,...e},true;let T=typeof e.confirmations=="number"?e.confirmations:0,d=typeof o.confirmations=="number"?o.confirmations:0;return T>d?(n[e.txKey]={...o,...e},true):false}}return n[e.txKey]=e,true};function Me({localTransactionsPool:n,reconcileUnsyncedTransactions:e,getHistory:o,onHistoryFetched:T}){let d=s=>({isLoading:s,isError:false}),p=s=>{if(!s)return {isLoading:false};let t=ae(s.docs);return T&&queueMicrotask(()=>T(t)),r=>q(r,c=>{let a=c.transactionsPool;for(let i of t)V(a,i);c.currentPage=s.page,c.hasMore=s.hasNextPage,c.isLoading=false;})};return vanilla.createStore()((s,t)=>({transactionsPool:n,isLoading:false,isError:false,hasMore:false,currentPage:1,syncWithLocalPool:r=>{s(c=>q(c,a=>{let i=a.transactionsPool;for(let l of Object.values(r))V(i,l);}));},fetchInitial:async r=>{if(!(!o||!r)){s(d(true)),e&&await e();try{let c=await o({page:1,walletAddress:r});s(p(c));}catch(c){console.error("[Pulsar] Failed to fetch initial transaction history:",c),s({isLoading:false,isError:true});}}},fetchNextPage:async r=>{let{hasMore:c,isLoading:a,currentPage:i}=t();if(!(!o||!c||a||!r)){s(d(true));try{let l=i+1,x=await o({page:l,walletAddress:r});s(p(x));}catch(l){console.error(`[Pulsar] Failed to fetch transaction history page ${i+1}:`,l),s({isLoading:false,isError:true});}}}}))}function Ye({adapter:n,maxTransactions:e=50,onRemoteCreate:o,gelatoApiKey:T,beforeTxProcess:d,abortOnTxError:p,...s}){return vanilla.createStore()(middleware.persist((t,r)=>({...G({maxTransactions:e,onRemoteCreate:o})(t,r),getAdapter:()=>n,initializeTransactionsPool:async()=>{let a=Object.values(r().transactionsPool).filter(i=>i.pending).filter(i=>{try{return S(i),!0}catch(l){return console.warn("[Pulsar] Removed invalid persisted transaction:",l),r().removeTxFromPool(i.txKey),false}});await Promise.all(a.map(i=>orbitCore.selectAdapterByKey({adapterKey:i.adapter,adapter:n})?.checkAndInitializeTrackerInStore({tx:i,gelatoApiKey:T,...r()})));},injectExternalPendingTxs:async c=>{let i=r().getAdapter(),l=[],x=c.filter(y=>{try{return S(y),!0}catch(m){return console.warn("[Pulsar] Skipped invalid remote transaction:",m),false}});t(y=>immer.produce(y,m=>{let b=m.transactionsPool;x.forEach(u=>{let g=b[u.txKey];u.pending&&!g&&(b[u.txKey]=u,l.push(u));let I=u.status==="Success"||u.status==="Failed"||u.status==="Replaced";g?.pending&&I&&(g.status=u.status,g.pending=false,u.txKey&&(g.txKey=u.txKey),u.finishedTimestamp&&(g.finishedTimestamp=u.finishedTimestamp));});})),l.length>0&&await Promise.all(l.map(y=>orbitCore.selectAdapterByKey({adapterKey:y.adapter,adapter:i})?.checkAndInitializeTrackerInStore({tx:y,gelatoApiKey:T,...r()})));},executeTxAction:async({defaultTracker:c,actionFunction:a,params:i,beforeTxProcess:l,abortOnTxError:x,...y})=>{let m=x??p??true,b=ce__default.default().unix();r().reconcileUnsyncedTransactions().catch(f=>console.error("[Pulsar] Reconciliation failed:",f)),$(i);let{desiredChainID:u,tracker:g,...I}=i,{onSuccess:W,onError:J,onReplaced:Y}=y;t({initialTx:{...i,actionFunction:a,localTimestamp:b,isInitializing:true}});let A=orbitCore.selectAdapterByKey({adapterKey:I.adapter,adapter:n}),z=f=>{t(E=>immer.produce(E,h=>{h.initialTx&&(h.initialTx.isInitializing=false,h.initialTx.error=orbitCore.normalizeError(f));}));};if(!A){let f=new Error("No adapter found for this transaction.");throw z(f),f}try{let{connectorType:f,walletAddress:E}=A.getConnectorInfo();await A.checkChainForTx(u);try{await(l??d)?.();}catch(v){if(m)throw t({initialTx:{...i,actionFunction:a,localTimestamp:b,isInitializing:!1,error:orbitCore.normalizeError(v)}}),v;console.warn("[Pulsar] beforeTxProcess failed:",v);}let h=await a();if(!h){t({initialTx:void 0});return}let{tracker:M,txKey:R}=A.checkTransactionsTracker({actionTxKey:h,connectorType:f,tracker:g,gelatoApiKey:i.gelatoApiKey??T,bundlerUrl:i.bundlerUrl,pimlicoApiKey:i.pimlicoApiKey}),Q={...I,connectorType:f,from:E,tracker:M||c,chainId:orbitCore.setChainId(u),localTimestamp:b,txKey:R,bundlerUrl:i.bundlerUrl,pimlicoApiKey:i.pimlicoApiKey,hash:M==="ethereum"?h:void 0,pending:!1,isTrackedModalOpen:i.withTrackedModal};await r().addTxToPool(Q),t(v=>immer.produce(v,F=>{F.initialTx&&(F.initialTx.isInitializing=!1,F.initialTx.lastTxKey=R);}));let Z=r().transactionsPool[R];await A.checkAndInitializeTrackerInStore({tx:Z,onSuccess:W,onError:J,onReplaced:Y,gelatoApiKey:T,...r()});}catch(f){throw z(f),f}}}),{partialize:t=>{let r={...t};return delete r.initialTx,r},merge:(t,r)=>({...r,...t,initialTx:r.initialTx}),...s}))}var nn=(n=>e=>zustand.useStore(n,e));function rn({tx:n,transactionsPool:e,updateTxParams:o}){let T=e[n.txKey];return d=>(o(n.txKey,d),T&&(T={...T,...d}),T)}var pe=5e3,ue=10;function an(n){let{tx:e,fetcher:o,onInitialize:T,onSuccess:d,onFailure:p,onIntervalTick:s,onReplaced:t,removeTxFromPool:r,pollingInterval:c=pe,maxRetries:a=ue}=n;if(!e.pending)return;T?.();let i=a,l=true,x=m=>{l&&(l=false,r&&!m?.withoutRemoving&&r(e.txKey));};(async()=>{for(;l&&i>0;)try{if(await new Promise(m=>setTimeout(m,c)),!l)break;await o({tx:e,stopPolling:x,onSuccess:d,onFailure:p,onIntervalTick:s,onReplaced:t}),i=a;}catch(m){console.error(`Polling fetcher for txKey ${e.txKey} threw an error:`,m),i--;}i<=0&&(console.warn(`Polling for txKey ${e.txKey} stopped after reaching the maximum number of retries.`),p(),x());})();}exports.MAX_TRANSACTION_DESCRIPTION_LENGTH=B;exports.MAX_TRANSACTION_PAYLOAD_BYTES=N;exports.MAX_TRANSACTION_TITLE_LENGTH=U;exports.PulsarTransactionValidationError=P;exports.TransactionStatus=K;exports.TransactionTracker=ee;exports.createBoundedUseStore=nn;exports.createPulsarStore=Ye;exports.createTxInMemoryStore=Me;exports.createTxUpdater=rn;exports.initializePollingTracker=an;exports.initializeTxTrackingStore=G;exports.selectAllTransactions=D;exports.selectAllTransactionsByActiveWallet=re;exports.selectPendingTransactions=Ae;exports.selectPendingTransactionsByActiveWallet=Ie;exports.selectTxByKey=ve;exports.validateInitialTransactionParams=$;exports.validateTransaction=S;
1
+ 'use strict';var immer=require('immer'),oe=require('dayjs'),vanilla=require('zustand/vanilla'),orbitCore=require('@tuwaio/orbit-core'),middleware=require('zustand/middleware'),zustand=require('zustand');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var oe__default=/*#__PURE__*/_interopDefault(oe);var re=(s=>(s.Ethereum="ethereum",s.Safe="safe",s.Gelato="gelato",s.Solana="solana",s.ERC4337="erc4337",s.EIP5792="eip5792",s))(re||{}),w=(d=>(d.Failed="Failed",d.Success="Success",d.Replaced="Replaced",d))(w||{});var E=30;function R(e,n,o=oe__default.default().unix()){if(n===null)return [];let d=o-n*24*60*60;return Object.values(e).filter(l=>!l.pending&&(l.finishedTimestamp??l.localTimestamp)<d).map(l=>l.txKey)}var $=100,j=300,_=10*1024,ie=[/\beval\s*\(/i,/\bFunction\s*\(/,/\bset(?:Timeout|Interval)\s*\(\s*['"`]/i,/javascript\s*:/i],P=class extends Error{field;constructor(n,o){super(o),this.name="PulsarTransactionValidationError",this.field=n;}};function D(e){F({field:"title",value:e.title,maxLength:$}),F({field:"description",value:e.description,maxLength:j}),G(e.payload);}function S(e){F({field:"title",value:e.title,maxLength:$}),F({field:"description",value:e.description,maxLength:j}),G(e.payload);}function F({field:e,value:n,maxLength:o}){if(n===void 0)return;(Array.isArray(n)?n:[n]).forEach((l,p)=>{let s=Array.isArray(n)?`${e}[${p}]`:e;if(typeof l!="string")throw new P(s,`${s} must be a string.`);if(l.length>o)throw new P(s,`${s} must be ${o} characters or less.`);C(s,l);});}function G(e){if(e===void 0)return;let n;try{n=JSON.stringify(e);}catch{throw new P("payload","payload must be JSON-serializable.")}if(n===void 0)throw new P("payload","payload must be JSON-serializable.");if(new TextEncoder().encode(n).length>_)throw new P("payload",`payload must be ${_} bytes or less when serialized.`);q(e);}function q(e,n="payload"){if(typeof e=="string"){C(n,e);return}e===null||typeof e!="object"||Object.entries(e).forEach(([o,d])=>{let l=`${n}.${o}`;C(l,o),q(d,l);});}function C(e,n){if(ie.some(o=>o.test(n)))throw new P(e,`${e} contains a blocked executable-like pattern.`)}function ae(e){let n={...e};return delete n.pimlicoApiKey,delete n.gelatoApiKey,n}function H({maxTransactions:e,retentionDays:n=E,onRemoteCreate:o}){let d=false,l=new Set;return (p,s)=>{let m=async(t,r)=>{let c=s().transactionsPool[t];if(!(!o||!c||l.has(t))){l.add(t);try{await o(ae(c)),p(i=>immer.produce(i,a=>{let T=a.transactionsPool[t];T&&(T.syncStatus="synced"),a.unsyncedTxKeys&&delete a.unsyncedTxKeys[t];}));}catch(i){console.warn(r,i);}finally{l.delete(t);}}};return {transactionsPool:{},lastAddedTxKey:void 0,initialTx:void 0,unsyncedTxKeys:{},reconcileUnsyncedTransactions:async()=>{if(!o||d)return;let t=Object.keys(s().unsyncedTxKeys||{});if(t.length!==0){d=true;try{for(let r of t){if(!s().transactionsPool[r]){p(c=>immer.produce(c,i=>{i.unsyncedTxKeys&&delete i.unsyncedTxKeys[r];}));continue}await m(r,`[Pulsar] Failed to reconcile tx ${r}:`);}}finally{d=false;}}},addTxToPool:t=>{S(t);let r={...t,pending:true,...o&&{syncStatus:"pending-sync"}};return p(c=>immer.produce(c,i=>{if(i.lastAddedTxKey=t.txKey,t.txKey){o&&(i.unsyncedTxKeys||(i.unsyncedTxKeys={}),i.unsyncedTxKeys[t.txKey]=true);for(let T of R(c.transactionsPool,n))delete i.transactionsPool[T],i.unsyncedTxKeys&&delete i.unsyncedTxKeys[T];if(Object.keys(i.transactionsPool).length>=e){let T=Object.values(i.transactionsPool).sort((y,u)=>y.localTimestamp-u.localTimestamp);if(T.length>0){let y=T[0];delete i.transactionsPool[y.txKey];}}i.transactionsPool[t.txKey]=r;}})),o&&t.txKey&&m(t.txKey,"[Pulsar] onRemoteCreate failed, transaction queued for background sync:"),Promise.resolve()},updateTxParams:(t,r)=>{p(i=>immer.produce(i,a=>{let T=a.transactionsPool[t];T&&Object.assign(T,r);})),(r.status==="Success"||r.status==="Failed"||r.status==="Replaced")&&s().reconcileUnsyncedTransactions&&s().unsyncedTxKeys?.[t]&&s().reconcileUnsyncedTransactions().catch(i=>{console.error("[Pulsar] Terminal reconciliation failed:",i);});},removeTxFromPool:t=>{p(r=>immer.produce(r,c=>{delete c.transactionsPool[t];}));},closeTxTrackedModal:t=>{p(r=>immer.produce(r,c=>{if(t&&c.transactionsPool[t]){let i=c.transactionsPool[t];c.transactionsPool[t]={...i,isTrackedModalOpen:false};}c.initialTx=void 0;}));},getLastTxKey:()=>s().lastAddedTxKey}}}var V=e=>Object.values(e).sort((n,o)=>Number(n.localTimestamp)-Number(o.localTimestamp)),Oe=e=>V(e).filter(n=>n.pending),Le=(e,n)=>e[n],se=(e,n)=>V(e).filter(o=>o.from.toLowerCase()===n.toLowerCase()),Ne=(e,n)=>se(e,n).filter(o=>o.pending);var{produce:X}=new immer.Immer({autoFreeze:false}),Te=e=>e.filter(n=>{try{return S(n),!0}catch(o){return console.warn("[Pulsar] Skipped invalid transaction from history:",o),false}}),Y=e=>e==="Success"||e==="Failed"||e==="Replaced",W=(e,n)=>{let o=e[n.txKey];if(o){if(Y(o.status))return false;if(o.pending){if(Y(n.status))return e[n.txKey]={...o,...n},true;let d=typeof n.confirmations=="number"?n.confirmations:0,l=typeof o.confirmations=="number"?o.confirmations:0;return d>l?(e[n.txKey]={...o,...n},true):false}}return e[n.txKey]=n,true};function Ge({localTransactionsPool:e,reconcileUnsyncedTransactions:n,getHistory:o,onHistoryFetched:d}){let l=s=>({isLoading:s,isError:false}),p=s=>{if(!s)return {isLoading:false};let m=Te(s.docs);return d&&queueMicrotask(()=>d(m)),t=>X(t,r=>{let c=r.transactionsPool;for(let i of m)W(c,i);r.currentPage=s.page,r.hasMore=s.hasNextPage,r.isLoading=false;})};return vanilla.createStore()((s,m)=>({transactionsPool:e,isLoading:false,isError:false,hasMore:false,currentPage:1,syncWithLocalPool:t=>{s(r=>X(r,c=>{let i=c.transactionsPool;for(let a of Object.values(t))W(i,a);}));},fetchInitial:async t=>{if(!(!o||!t)){s(l(true)),n&&await n();try{let r=await o({page:1,walletAddress:t});s(p(r));}catch(r){console.error("[Pulsar] Failed to fetch initial transaction history:",r),s({isLoading:false,isError:true});}}},fetchNextPage:async t=>{let{hasMore:r,isLoading:c,currentPage:i}=m();if(!(!o||!r||c||!t)){s(l(true));try{let a=i+1,T=await o({page:a,walletAddress:t});s(p(T));}catch(a){console.error(`[Pulsar] Failed to fetch transaction history page ${i+1}:`,a),s({isLoading:false,isError:true});}}}}))}function sn({adapter:e,maxTransactions:n=50,retentionDays:o=E,onRemoteCreate:d,gelatoApiKey:l,beforeTxProcess:p,abortOnTxError:s,...m}){return vanilla.createStore()(middleware.persist((t,r)=>({...H({maxTransactions:n,retentionDays:o,onRemoteCreate:d})(t,r),getAdapter:()=>e,initializeTransactionsPool:async()=>{let i=Object.values(r().transactionsPool).filter(a=>a.pending).filter(a=>{try{return S(a),!0}catch(T){return console.warn("[Pulsar] Removed invalid persisted transaction:",T),r().removeTxFromPool(a.txKey),false}});await Promise.all(i.map(a=>orbitCore.selectAdapterByKey({adapterKey:a.adapter,adapter:e})?.checkAndInitializeTrackerInStore({tx:a,gelatoApiKey:l,...r()})));},injectExternalPendingTxs:async c=>{let a=r().getAdapter(),T=[],y=c.filter(u=>{try{return S(u),!0}catch(b){return console.warn("[Pulsar] Skipped invalid remote transaction:",b),false}});t(u=>immer.produce(u,b=>{let A=b.transactionsPool;y.forEach(x=>{let g=A[x.txKey];x.pending&&!g&&(A[x.txKey]=x,T.push(x));let K=x.status==="Success"||x.status==="Failed"||x.status==="Replaced";g?.pending&&K&&(g.status=x.status,g.pending=false,x.txKey&&(g.txKey=x.txKey),x.finishedTimestamp&&(g.finishedTimestamp=x.finishedTimestamp));});})),T.length>0&&await Promise.all(T.map(u=>orbitCore.selectAdapterByKey({adapterKey:u.adapter,adapter:a})?.checkAndInitializeTrackerInStore({tx:u,gelatoApiKey:l,...r()})));},executeTxAction:async({defaultTracker:c,actionFunction:i,params:a,beforeTxProcess:T,abortOnTxError:y,...u})=>{let b=y??s??true,A=oe__default.default().unix();r().reconcileUnsyncedTransactions().catch(f=>console.error("[Pulsar] Reconciliation failed:",f)),D(a);let{desiredChainID:x,tracker:g,...K}=a,{onSuccess:Q,onError:Z,onReplaced:ee}=u;t({initialTx:{...a,actionFunction:i,localTimestamp:A,isInitializing:true}});let v=orbitCore.selectAdapterByKey({adapterKey:K.adapter,adapter:e}),M=f=>{t(O=>immer.produce(O,h=>{h.initialTx&&(h.initialTx.isInitializing=false,h.initialTx.error=orbitCore.normalizeError(f));}));};if(!v){let f=new Error("No adapter found for this transaction.");throw M(f),f}try{let{connectorType:f,walletAddress:O}=v.getConnectorInfo();await v.checkChainForTx(x);try{await(T??p)?.();}catch(I){if(b)throw t({initialTx:{...a,actionFunction:i,localTimestamp:A,isInitializing:!1,error:orbitCore.normalizeError(I)}}),I;console.warn("[Pulsar] beforeTxProcess failed:",I);}let h=await i();if(!h){t({initialTx:void 0});return}let{tracker:B,txKey:L}=v.checkTransactionsTracker({actionTxKey:h,connectorType:f,tracker:g,gelatoApiKey:a.gelatoApiKey??l,bundlerUrl:a.bundlerUrl,pimlicoApiKey:a.pimlicoApiKey}),ne={...K,connectorType:f,from:O,tracker:B||c,chainId:orbitCore.setChainId(x),localTimestamp:A,txKey:L,bundlerUrl:a.bundlerUrl,pimlicoApiKey:a.pimlicoApiKey,hash:B==="ethereum"?h:void 0,pending:!1,isTrackedModalOpen:a.withTrackedModal};await r().addTxToPool(ne),t(I=>immer.produce(I,N=>{N.initialTx&&(N.initialTx.isInitializing=!1,N.initialTx.lastTxKey=L);}));let te=r().transactionsPool[L];await v.checkAndInitializeTrackerInStore({tx:te,onSuccess:Q,onError:Z,onReplaced:ee,gelatoApiKey:l,...r()});}catch(f){throw M(f),f}}}),{partialize:t=>{let r={...t};return delete r.initialTx,r},...m,merge:(t,r)=>{let c=m.merge?m.merge(t,r):{...r,...t,initialTx:r.initialTx},i=R(c.transactionsPool??{},o);if(i.length===0)return c;let a={...c.transactionsPool},T=c.unsyncedTxKeys?{...c.unsyncedTxKeys}:c.unsyncedTxKeys;for(let y of i)delete a[y],T&&delete T[y];return {...c,transactionsPool:a,unsyncedTxKeys:T}}}))}var dn=(e=>n=>zustand.useStore(e,n));function un({tx:e,transactionsPool:n,updateTxParams:o}){let d=n[e.txKey];return l=>(o(e.txKey,l),d&&(d={...d,...l}),d)}var fe=5e3,ye=10;function mn(e){let{tx:n,fetcher:o,onInitialize:d,onSuccess:l,onFailure:p,onIntervalTick:s,onReplaced:m,removeTxFromPool:t,pollingInterval:r=fe,maxRetries:c=ye}=e;if(!n.pending)return;d?.();let i=c,a=true,T=u=>{a&&(a=false,t&&!u?.withoutRemoving&&t(n.txKey));};(async()=>{for(;a&&i>0;)try{if(await new Promise(u=>setTimeout(u,r)),!a)break;await o({tx:n,stopPolling:T,onSuccess:l,onFailure:p,onIntervalTick:s,onReplaced:m}),i=c;}catch(u){console.error(`Polling fetcher for txKey ${n.txKey} threw an error:`,u),i--;}i<=0&&(console.warn(`Polling for txKey ${n.txKey} stopped after reaching the maximum number of retries.`),p(),T());})();}exports.MAX_TRANSACTION_DESCRIPTION_LENGTH=j;exports.MAX_TRANSACTION_PAYLOAD_BYTES=_;exports.MAX_TRANSACTION_TITLE_LENGTH=$;exports.PulsarTransactionValidationError=P;exports.TransactionStatus=w;exports.TransactionTracker=re;exports.createBoundedUseStore=dn;exports.createPulsarStore=sn;exports.createTxInMemoryStore=Ge;exports.createTxUpdater=un;exports.initializePollingTracker=mn;exports.initializeTxTrackingStore=H;exports.selectAllTransactions=V;exports.selectAllTransactionsByActiveWallet=se;exports.selectPendingTransactions=Oe;exports.selectPendingTransactionsByActiveWallet=Ne;exports.selectTxByKey=Le;exports.validateInitialTransactionParams=D;exports.validateTransaction=S;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import {Immer,produce}from'immer';import {createStore}from'zustand/vanilla';import {selectAdapterByKey,normalizeError,setChainId}from'@tuwaio/orbit-core';import ce from'dayjs';import {persist}from'zustand/middleware';import {useStore}from'zustand';var ee=(s=>(s.Ethereum="ethereum",s.Safe="safe",s.Gelato="gelato",s.Solana="solana",s.ERC4337="erc4337",s.EIP5792="eip5792",s))(ee||{}),K=(T=>(T.Failed="Failed",T.Success="Success",T.Replaced="Replaced",T))(K||{});var U=100,B=300,N=10*1024,ne=[/\beval\s*\(/i,/\bFunction\s*\(/,/\bset(?:Timeout|Interval)\s*\(\s*['"`]/i,/javascript\s*:/i],P=class extends Error{field;constructor(e,o){super(o),this.name="PulsarTransactionValidationError",this.field=e;}};function $(n){w({field:"title",value:n.title,maxLength:U}),w({field:"description",value:n.description,maxLength:B}),j(n.payload);}function S(n){w({field:"title",value:n.title,maxLength:U}),w({field:"description",value:n.description,maxLength:B}),j(n.payload);}function w({field:n,value:e,maxLength:o}){if(e===void 0)return;(Array.isArray(e)?e:[e]).forEach((d,p)=>{let s=Array.isArray(e)?`${n}[${p}]`:n;if(typeof d!="string")throw new P(s,`${s} must be a string.`);if(d.length>o)throw new P(s,`${s} must be ${o} characters or less.`);O(s,d);});}function j(n){if(n===void 0)return;let e;try{e=JSON.stringify(n);}catch{throw new P("payload","payload must be JSON-serializable.")}if(e===void 0)throw new P("payload","payload must be JSON-serializable.");if(new TextEncoder().encode(e).length>N)throw new P("payload",`payload must be ${N} bytes or less when serialized.`);_(n);}function _(n,e="payload"){if(typeof n=="string"){O(e,n);return}n===null||typeof n!="object"||Object.entries(n).forEach(([o,T])=>{let d=`${e}.${o}`;O(d,o),_(T,d);});}function O(n,e){if(ne.some(o=>o.test(e)))throw new P(n,`${n} contains a blocked executable-like pattern.`)}function te(n){let e={...n};return delete e.pimlicoApiKey,delete e.gelatoApiKey,e}function G({maxTransactions:n,onRemoteCreate:e}){let o=false,T=new Set;return (d,p)=>{let s=async(t,r)=>{let c=p().transactionsPool[t];if(!(!e||!c||T.has(t))){T.add(t);try{await e(te(c)),d(a=>produce(a,i=>{let l=i.transactionsPool[t];l&&(l.syncStatus="synced"),i.unsyncedTxKeys&&delete i.unsyncedTxKeys[t];}));}catch(a){console.warn(r,a);}finally{T.delete(t);}}};return {transactionsPool:{},lastAddedTxKey:void 0,initialTx:void 0,unsyncedTxKeys:{},reconcileUnsyncedTransactions:async()=>{if(!e||o)return;let t=Object.keys(p().unsyncedTxKeys||{});if(t.length!==0){o=true;try{for(let r of t){if(!p().transactionsPool[r]){d(c=>produce(c,a=>{a.unsyncedTxKeys&&delete a.unsyncedTxKeys[r];}));continue}await s(r,`[Pulsar] Failed to reconcile tx ${r}:`);}}finally{o=false;}}},addTxToPool:t=>{S(t);let r={...t,pending:true,...e&&{syncStatus:"pending-sync"}};return d(c=>produce(c,a=>{if(a.lastAddedTxKey=t.txKey,t.txKey){if(e&&(a.unsyncedTxKeys||(a.unsyncedTxKeys={}),a.unsyncedTxKeys[t.txKey]=true),Object.keys(a.transactionsPool).length>=n){let l=Object.values(a.transactionsPool).sort((x,y)=>x.localTimestamp-y.localTimestamp);if(l.length>0){let x=l[0];delete a.transactionsPool[x.txKey];}}a.transactionsPool[t.txKey]=r;}})),e&&t.txKey&&s(t.txKey,"[Pulsar] onRemoteCreate failed, transaction queued for background sync:"),Promise.resolve()},updateTxParams:(t,r)=>{d(a=>produce(a,i=>{let l=i.transactionsPool[t];l&&Object.assign(l,r);})),(r.status==="Success"||r.status==="Failed"||r.status==="Replaced")&&p().reconcileUnsyncedTransactions&&p().unsyncedTxKeys?.[t]&&p().reconcileUnsyncedTransactions().catch(a=>{console.error("[Pulsar] Terminal reconciliation failed:",a);});},removeTxFromPool:t=>{d(r=>produce(r,c=>{delete c.transactionsPool[t];}));},closeTxTrackedModal:t=>{d(r=>produce(r,c=>{if(t&&c.transactionsPool[t]){let a=c.transactionsPool[t];c.transactionsPool[t]={...a,isTrackedModalOpen:false};}c.initialTx=void 0;}));},getLastTxKey:()=>p().lastAddedTxKey}}}var D=n=>Object.values(n).sort((e,o)=>Number(e.localTimestamp)-Number(o.localTimestamp)),Ae=n=>D(n).filter(e=>e.pending),ve=(n,e)=>n[e],re=(n,e)=>D(n).filter(o=>o.from.toLowerCase()===e.toLowerCase()),Ie=(n,e)=>re(n,e).filter(o=>o.pending);var{produce:q}=new Immer({autoFreeze:false}),ae=n=>n.filter(e=>{try{return S(e),!0}catch(o){return console.warn("[Pulsar] Skipped invalid transaction from history:",o),false}}),H=n=>n==="Success"||n==="Failed"||n==="Replaced",V=(n,e)=>{let o=n[e.txKey];if(o){if(H(o.status))return false;if(o.pending){if(H(e.status))return n[e.txKey]={...o,...e},true;let T=typeof e.confirmations=="number"?e.confirmations:0,d=typeof o.confirmations=="number"?o.confirmations:0;return T>d?(n[e.txKey]={...o,...e},true):false}}return n[e.txKey]=e,true};function Me({localTransactionsPool:n,reconcileUnsyncedTransactions:e,getHistory:o,onHistoryFetched:T}){let d=s=>({isLoading:s,isError:false}),p=s=>{if(!s)return {isLoading:false};let t=ae(s.docs);return T&&queueMicrotask(()=>T(t)),r=>q(r,c=>{let a=c.transactionsPool;for(let i of t)V(a,i);c.currentPage=s.page,c.hasMore=s.hasNextPage,c.isLoading=false;})};return createStore()((s,t)=>({transactionsPool:n,isLoading:false,isError:false,hasMore:false,currentPage:1,syncWithLocalPool:r=>{s(c=>q(c,a=>{let i=a.transactionsPool;for(let l of Object.values(r))V(i,l);}));},fetchInitial:async r=>{if(!(!o||!r)){s(d(true)),e&&await e();try{let c=await o({page:1,walletAddress:r});s(p(c));}catch(c){console.error("[Pulsar] Failed to fetch initial transaction history:",c),s({isLoading:false,isError:true});}}},fetchNextPage:async r=>{let{hasMore:c,isLoading:a,currentPage:i}=t();if(!(!o||!c||a||!r)){s(d(true));try{let l=i+1,x=await o({page:l,walletAddress:r});s(p(x));}catch(l){console.error(`[Pulsar] Failed to fetch transaction history page ${i+1}:`,l),s({isLoading:false,isError:true});}}}}))}function Ye({adapter:n,maxTransactions:e=50,onRemoteCreate:o,gelatoApiKey:T,beforeTxProcess:d,abortOnTxError:p,...s}){return createStore()(persist((t,r)=>({...G({maxTransactions:e,onRemoteCreate:o})(t,r),getAdapter:()=>n,initializeTransactionsPool:async()=>{let a=Object.values(r().transactionsPool).filter(i=>i.pending).filter(i=>{try{return S(i),!0}catch(l){return console.warn("[Pulsar] Removed invalid persisted transaction:",l),r().removeTxFromPool(i.txKey),false}});await Promise.all(a.map(i=>selectAdapterByKey({adapterKey:i.adapter,adapter:n})?.checkAndInitializeTrackerInStore({tx:i,gelatoApiKey:T,...r()})));},injectExternalPendingTxs:async c=>{let i=r().getAdapter(),l=[],x=c.filter(y=>{try{return S(y),!0}catch(m){return console.warn("[Pulsar] Skipped invalid remote transaction:",m),false}});t(y=>produce(y,m=>{let b=m.transactionsPool;x.forEach(u=>{let g=b[u.txKey];u.pending&&!g&&(b[u.txKey]=u,l.push(u));let I=u.status==="Success"||u.status==="Failed"||u.status==="Replaced";g?.pending&&I&&(g.status=u.status,g.pending=false,u.txKey&&(g.txKey=u.txKey),u.finishedTimestamp&&(g.finishedTimestamp=u.finishedTimestamp));});})),l.length>0&&await Promise.all(l.map(y=>selectAdapterByKey({adapterKey:y.adapter,adapter:i})?.checkAndInitializeTrackerInStore({tx:y,gelatoApiKey:T,...r()})));},executeTxAction:async({defaultTracker:c,actionFunction:a,params:i,beforeTxProcess:l,abortOnTxError:x,...y})=>{let m=x??p??true,b=ce().unix();r().reconcileUnsyncedTransactions().catch(f=>console.error("[Pulsar] Reconciliation failed:",f)),$(i);let{desiredChainID:u,tracker:g,...I}=i,{onSuccess:W,onError:J,onReplaced:Y}=y;t({initialTx:{...i,actionFunction:a,localTimestamp:b,isInitializing:true}});let A=selectAdapterByKey({adapterKey:I.adapter,adapter:n}),z=f=>{t(E=>produce(E,h=>{h.initialTx&&(h.initialTx.isInitializing=false,h.initialTx.error=normalizeError(f));}));};if(!A){let f=new Error("No adapter found for this transaction.");throw z(f),f}try{let{connectorType:f,walletAddress:E}=A.getConnectorInfo();await A.checkChainForTx(u);try{await(l??d)?.();}catch(v){if(m)throw t({initialTx:{...i,actionFunction:a,localTimestamp:b,isInitializing:!1,error:normalizeError(v)}}),v;console.warn("[Pulsar] beforeTxProcess failed:",v);}let h=await a();if(!h){t({initialTx:void 0});return}let{tracker:M,txKey:R}=A.checkTransactionsTracker({actionTxKey:h,connectorType:f,tracker:g,gelatoApiKey:i.gelatoApiKey??T,bundlerUrl:i.bundlerUrl,pimlicoApiKey:i.pimlicoApiKey}),Q={...I,connectorType:f,from:E,tracker:M||c,chainId:setChainId(u),localTimestamp:b,txKey:R,bundlerUrl:i.bundlerUrl,pimlicoApiKey:i.pimlicoApiKey,hash:M==="ethereum"?h:void 0,pending:!1,isTrackedModalOpen:i.withTrackedModal};await r().addTxToPool(Q),t(v=>produce(v,F=>{F.initialTx&&(F.initialTx.isInitializing=!1,F.initialTx.lastTxKey=R);}));let Z=r().transactionsPool[R];await A.checkAndInitializeTrackerInStore({tx:Z,onSuccess:W,onError:J,onReplaced:Y,gelatoApiKey:T,...r()});}catch(f){throw z(f),f}}}),{partialize:t=>{let r={...t};return delete r.initialTx,r},merge:(t,r)=>({...r,...t,initialTx:r.initialTx}),...s}))}var nn=(n=>e=>useStore(n,e));function rn({tx:n,transactionsPool:e,updateTxParams:o}){let T=e[n.txKey];return d=>(o(n.txKey,d),T&&(T={...T,...d}),T)}var pe=5e3,ue=10;function an(n){let{tx:e,fetcher:o,onInitialize:T,onSuccess:d,onFailure:p,onIntervalTick:s,onReplaced:t,removeTxFromPool:r,pollingInterval:c=pe,maxRetries:a=ue}=n;if(!e.pending)return;T?.();let i=a,l=true,x=m=>{l&&(l=false,r&&!m?.withoutRemoving&&r(e.txKey));};(async()=>{for(;l&&i>0;)try{if(await new Promise(m=>setTimeout(m,c)),!l)break;await o({tx:e,stopPolling:x,onSuccess:d,onFailure:p,onIntervalTick:s,onReplaced:t}),i=a;}catch(m){console.error(`Polling fetcher for txKey ${e.txKey} threw an error:`,m),i--;}i<=0&&(console.warn(`Polling for txKey ${e.txKey} stopped after reaching the maximum number of retries.`),p(),x());})();}export{B as MAX_TRANSACTION_DESCRIPTION_LENGTH,N as MAX_TRANSACTION_PAYLOAD_BYTES,U as MAX_TRANSACTION_TITLE_LENGTH,P as PulsarTransactionValidationError,K as TransactionStatus,ee as TransactionTracker,nn as createBoundedUseStore,Ye as createPulsarStore,Me as createTxInMemoryStore,rn as createTxUpdater,an as initializePollingTracker,G as initializeTxTrackingStore,D as selectAllTransactions,re as selectAllTransactionsByActiveWallet,Ae as selectPendingTransactions,Ie as selectPendingTransactionsByActiveWallet,ve as selectTxByKey,$ as validateInitialTransactionParams,S as validateTransaction};
1
+ import {Immer,produce}from'immer';import oe from'dayjs';import {createStore}from'zustand/vanilla';import {selectAdapterByKey,normalizeError,setChainId}from'@tuwaio/orbit-core';import {persist}from'zustand/middleware';import {useStore}from'zustand';var re=(s=>(s.Ethereum="ethereum",s.Safe="safe",s.Gelato="gelato",s.Solana="solana",s.ERC4337="erc4337",s.EIP5792="eip5792",s))(re||{}),w=(d=>(d.Failed="Failed",d.Success="Success",d.Replaced="Replaced",d))(w||{});var E=30;function R(e,n,o=oe().unix()){if(n===null)return [];let d=o-n*24*60*60;return Object.values(e).filter(l=>!l.pending&&(l.finishedTimestamp??l.localTimestamp)<d).map(l=>l.txKey)}var $=100,j=300,_=10*1024,ie=[/\beval\s*\(/i,/\bFunction\s*\(/,/\bset(?:Timeout|Interval)\s*\(\s*['"`]/i,/javascript\s*:/i],P=class extends Error{field;constructor(n,o){super(o),this.name="PulsarTransactionValidationError",this.field=n;}};function D(e){F({field:"title",value:e.title,maxLength:$}),F({field:"description",value:e.description,maxLength:j}),G(e.payload);}function S(e){F({field:"title",value:e.title,maxLength:$}),F({field:"description",value:e.description,maxLength:j}),G(e.payload);}function F({field:e,value:n,maxLength:o}){if(n===void 0)return;(Array.isArray(n)?n:[n]).forEach((l,p)=>{let s=Array.isArray(n)?`${e}[${p}]`:e;if(typeof l!="string")throw new P(s,`${s} must be a string.`);if(l.length>o)throw new P(s,`${s} must be ${o} characters or less.`);C(s,l);});}function G(e){if(e===void 0)return;let n;try{n=JSON.stringify(e);}catch{throw new P("payload","payload must be JSON-serializable.")}if(n===void 0)throw new P("payload","payload must be JSON-serializable.");if(new TextEncoder().encode(n).length>_)throw new P("payload",`payload must be ${_} bytes or less when serialized.`);q(e);}function q(e,n="payload"){if(typeof e=="string"){C(n,e);return}e===null||typeof e!="object"||Object.entries(e).forEach(([o,d])=>{let l=`${n}.${o}`;C(l,o),q(d,l);});}function C(e,n){if(ie.some(o=>o.test(n)))throw new P(e,`${e} contains a blocked executable-like pattern.`)}function ae(e){let n={...e};return delete n.pimlicoApiKey,delete n.gelatoApiKey,n}function H({maxTransactions:e,retentionDays:n=E,onRemoteCreate:o}){let d=false,l=new Set;return (p,s)=>{let m=async(t,r)=>{let c=s().transactionsPool[t];if(!(!o||!c||l.has(t))){l.add(t);try{await o(ae(c)),p(i=>produce(i,a=>{let T=a.transactionsPool[t];T&&(T.syncStatus="synced"),a.unsyncedTxKeys&&delete a.unsyncedTxKeys[t];}));}catch(i){console.warn(r,i);}finally{l.delete(t);}}};return {transactionsPool:{},lastAddedTxKey:void 0,initialTx:void 0,unsyncedTxKeys:{},reconcileUnsyncedTransactions:async()=>{if(!o||d)return;let t=Object.keys(s().unsyncedTxKeys||{});if(t.length!==0){d=true;try{for(let r of t){if(!s().transactionsPool[r]){p(c=>produce(c,i=>{i.unsyncedTxKeys&&delete i.unsyncedTxKeys[r];}));continue}await m(r,`[Pulsar] Failed to reconcile tx ${r}:`);}}finally{d=false;}}},addTxToPool:t=>{S(t);let r={...t,pending:true,...o&&{syncStatus:"pending-sync"}};return p(c=>produce(c,i=>{if(i.lastAddedTxKey=t.txKey,t.txKey){o&&(i.unsyncedTxKeys||(i.unsyncedTxKeys={}),i.unsyncedTxKeys[t.txKey]=true);for(let T of R(c.transactionsPool,n))delete i.transactionsPool[T],i.unsyncedTxKeys&&delete i.unsyncedTxKeys[T];if(Object.keys(i.transactionsPool).length>=e){let T=Object.values(i.transactionsPool).sort((y,u)=>y.localTimestamp-u.localTimestamp);if(T.length>0){let y=T[0];delete i.transactionsPool[y.txKey];}}i.transactionsPool[t.txKey]=r;}})),o&&t.txKey&&m(t.txKey,"[Pulsar] onRemoteCreate failed, transaction queued for background sync:"),Promise.resolve()},updateTxParams:(t,r)=>{p(i=>produce(i,a=>{let T=a.transactionsPool[t];T&&Object.assign(T,r);})),(r.status==="Success"||r.status==="Failed"||r.status==="Replaced")&&s().reconcileUnsyncedTransactions&&s().unsyncedTxKeys?.[t]&&s().reconcileUnsyncedTransactions().catch(i=>{console.error("[Pulsar] Terminal reconciliation failed:",i);});},removeTxFromPool:t=>{p(r=>produce(r,c=>{delete c.transactionsPool[t];}));},closeTxTrackedModal:t=>{p(r=>produce(r,c=>{if(t&&c.transactionsPool[t]){let i=c.transactionsPool[t];c.transactionsPool[t]={...i,isTrackedModalOpen:false};}c.initialTx=void 0;}));},getLastTxKey:()=>s().lastAddedTxKey}}}var V=e=>Object.values(e).sort((n,o)=>Number(n.localTimestamp)-Number(o.localTimestamp)),Oe=e=>V(e).filter(n=>n.pending),Le=(e,n)=>e[n],se=(e,n)=>V(e).filter(o=>o.from.toLowerCase()===n.toLowerCase()),Ne=(e,n)=>se(e,n).filter(o=>o.pending);var{produce:X}=new Immer({autoFreeze:false}),Te=e=>e.filter(n=>{try{return S(n),!0}catch(o){return console.warn("[Pulsar] Skipped invalid transaction from history:",o),false}}),Y=e=>e==="Success"||e==="Failed"||e==="Replaced",W=(e,n)=>{let o=e[n.txKey];if(o){if(Y(o.status))return false;if(o.pending){if(Y(n.status))return e[n.txKey]={...o,...n},true;let d=typeof n.confirmations=="number"?n.confirmations:0,l=typeof o.confirmations=="number"?o.confirmations:0;return d>l?(e[n.txKey]={...o,...n},true):false}}return e[n.txKey]=n,true};function Ge({localTransactionsPool:e,reconcileUnsyncedTransactions:n,getHistory:o,onHistoryFetched:d}){let l=s=>({isLoading:s,isError:false}),p=s=>{if(!s)return {isLoading:false};let m=Te(s.docs);return d&&queueMicrotask(()=>d(m)),t=>X(t,r=>{let c=r.transactionsPool;for(let i of m)W(c,i);r.currentPage=s.page,r.hasMore=s.hasNextPage,r.isLoading=false;})};return createStore()((s,m)=>({transactionsPool:e,isLoading:false,isError:false,hasMore:false,currentPage:1,syncWithLocalPool:t=>{s(r=>X(r,c=>{let i=c.transactionsPool;for(let a of Object.values(t))W(i,a);}));},fetchInitial:async t=>{if(!(!o||!t)){s(l(true)),n&&await n();try{let r=await o({page:1,walletAddress:t});s(p(r));}catch(r){console.error("[Pulsar] Failed to fetch initial transaction history:",r),s({isLoading:false,isError:true});}}},fetchNextPage:async t=>{let{hasMore:r,isLoading:c,currentPage:i}=m();if(!(!o||!r||c||!t)){s(l(true));try{let a=i+1,T=await o({page:a,walletAddress:t});s(p(T));}catch(a){console.error(`[Pulsar] Failed to fetch transaction history page ${i+1}:`,a),s({isLoading:false,isError:true});}}}}))}function sn({adapter:e,maxTransactions:n=50,retentionDays:o=E,onRemoteCreate:d,gelatoApiKey:l,beforeTxProcess:p,abortOnTxError:s,...m}){return createStore()(persist((t,r)=>({...H({maxTransactions:n,retentionDays:o,onRemoteCreate:d})(t,r),getAdapter:()=>e,initializeTransactionsPool:async()=>{let i=Object.values(r().transactionsPool).filter(a=>a.pending).filter(a=>{try{return S(a),!0}catch(T){return console.warn("[Pulsar] Removed invalid persisted transaction:",T),r().removeTxFromPool(a.txKey),false}});await Promise.all(i.map(a=>selectAdapterByKey({adapterKey:a.adapter,adapter:e})?.checkAndInitializeTrackerInStore({tx:a,gelatoApiKey:l,...r()})));},injectExternalPendingTxs:async c=>{let a=r().getAdapter(),T=[],y=c.filter(u=>{try{return S(u),!0}catch(b){return console.warn("[Pulsar] Skipped invalid remote transaction:",b),false}});t(u=>produce(u,b=>{let A=b.transactionsPool;y.forEach(x=>{let g=A[x.txKey];x.pending&&!g&&(A[x.txKey]=x,T.push(x));let K=x.status==="Success"||x.status==="Failed"||x.status==="Replaced";g?.pending&&K&&(g.status=x.status,g.pending=false,x.txKey&&(g.txKey=x.txKey),x.finishedTimestamp&&(g.finishedTimestamp=x.finishedTimestamp));});})),T.length>0&&await Promise.all(T.map(u=>selectAdapterByKey({adapterKey:u.adapter,adapter:a})?.checkAndInitializeTrackerInStore({tx:u,gelatoApiKey:l,...r()})));},executeTxAction:async({defaultTracker:c,actionFunction:i,params:a,beforeTxProcess:T,abortOnTxError:y,...u})=>{let b=y??s??true,A=oe().unix();r().reconcileUnsyncedTransactions().catch(f=>console.error("[Pulsar] Reconciliation failed:",f)),D(a);let{desiredChainID:x,tracker:g,...K}=a,{onSuccess:Q,onError:Z,onReplaced:ee}=u;t({initialTx:{...a,actionFunction:i,localTimestamp:A,isInitializing:true}});let v=selectAdapterByKey({adapterKey:K.adapter,adapter:e}),M=f=>{t(O=>produce(O,h=>{h.initialTx&&(h.initialTx.isInitializing=false,h.initialTx.error=normalizeError(f));}));};if(!v){let f=new Error("No adapter found for this transaction.");throw M(f),f}try{let{connectorType:f,walletAddress:O}=v.getConnectorInfo();await v.checkChainForTx(x);try{await(T??p)?.();}catch(I){if(b)throw t({initialTx:{...a,actionFunction:i,localTimestamp:A,isInitializing:!1,error:normalizeError(I)}}),I;console.warn("[Pulsar] beforeTxProcess failed:",I);}let h=await i();if(!h){t({initialTx:void 0});return}let{tracker:B,txKey:L}=v.checkTransactionsTracker({actionTxKey:h,connectorType:f,tracker:g,gelatoApiKey:a.gelatoApiKey??l,bundlerUrl:a.bundlerUrl,pimlicoApiKey:a.pimlicoApiKey}),ne={...K,connectorType:f,from:O,tracker:B||c,chainId:setChainId(x),localTimestamp:A,txKey:L,bundlerUrl:a.bundlerUrl,pimlicoApiKey:a.pimlicoApiKey,hash:B==="ethereum"?h:void 0,pending:!1,isTrackedModalOpen:a.withTrackedModal};await r().addTxToPool(ne),t(I=>produce(I,N=>{N.initialTx&&(N.initialTx.isInitializing=!1,N.initialTx.lastTxKey=L);}));let te=r().transactionsPool[L];await v.checkAndInitializeTrackerInStore({tx:te,onSuccess:Q,onError:Z,onReplaced:ee,gelatoApiKey:l,...r()});}catch(f){throw M(f),f}}}),{partialize:t=>{let r={...t};return delete r.initialTx,r},...m,merge:(t,r)=>{let c=m.merge?m.merge(t,r):{...r,...t,initialTx:r.initialTx},i=R(c.transactionsPool??{},o);if(i.length===0)return c;let a={...c.transactionsPool},T=c.unsyncedTxKeys?{...c.unsyncedTxKeys}:c.unsyncedTxKeys;for(let y of i)delete a[y],T&&delete T[y];return {...c,transactionsPool:a,unsyncedTxKeys:T}}}))}var dn=(e=>n=>useStore(e,n));function un({tx:e,transactionsPool:n,updateTxParams:o}){let d=n[e.txKey];return l=>(o(e.txKey,l),d&&(d={...d,...l}),d)}var fe=5e3,ye=10;function mn(e){let{tx:n,fetcher:o,onInitialize:d,onSuccess:l,onFailure:p,onIntervalTick:s,onReplaced:m,removeTxFromPool:t,pollingInterval:r=fe,maxRetries:c=ye}=e;if(!n.pending)return;d?.();let i=c,a=true,T=u=>{a&&(a=false,t&&!u?.withoutRemoving&&t(n.txKey));};(async()=>{for(;a&&i>0;)try{if(await new Promise(u=>setTimeout(u,r)),!a)break;await o({tx:n,stopPolling:T,onSuccess:l,onFailure:p,onIntervalTick:s,onReplaced:m}),i=c;}catch(u){console.error(`Polling fetcher for txKey ${n.txKey} threw an error:`,u),i--;}i<=0&&(console.warn(`Polling for txKey ${n.txKey} stopped after reaching the maximum number of retries.`),p(),T());})();}export{j as MAX_TRANSACTION_DESCRIPTION_LENGTH,_ as MAX_TRANSACTION_PAYLOAD_BYTES,$ as MAX_TRANSACTION_TITLE_LENGTH,P as PulsarTransactionValidationError,w as TransactionStatus,re as TransactionTracker,dn as createBoundedUseStore,sn as createPulsarStore,Ge as createTxInMemoryStore,un as createTxUpdater,mn as initializePollingTracker,H as initializeTxTrackingStore,V as selectAllTransactions,se as selectAllTransactionsByActiveWallet,Oe as selectPendingTransactions,Ne as selectPendingTransactionsByActiveWallet,Le as selectTxByKey,D as validateInitialTransactionParams,S as validateTransaction};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuwaio/pulsar-core",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "private": false,
5
5
  "author": "Oleksandr Tkach",
6
6
  "license": "Apache-2.0",
@@ -51,12 +51,12 @@
51
51
  "zustand": "5.x.x"
52
52
  },
53
53
  "devDependencies": {
54
- "@tuwaio/orbit-core": "^0.5.1",
54
+ "@tuwaio/orbit-core": "^0.6.0",
55
55
  "dayjs": "^1.11.23",
56
56
  "immer": "^11.1.21",
57
- "tsup": "^8.5.1",
57
+ "tsup": "^9.0.0",
58
58
  "typescript": "6.0.3",
59
- "vitest": "^5.0.3",
59
+ "vitest": "^5.0.5",
60
60
  "zustand": "^5.0.15"
61
61
  },
62
62
  "scripts": {