@tuwaio/pulsar-solana 0.3.3 → 0.3.5

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/index.js CHANGED
@@ -1,2 +1 @@
1
- 'use strict';var orbitCore=require('@tuwaio/orbit-core'),orbitSolana=require('@tuwaio/orbit-solana'),pulsarCore=require('@tuwaio/pulsar-core'),m=require('dayjs'),gill=require('gill');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var m__default=/*#__PURE__*/_interopDefault(m);var l=class extends Error{name="SolanaChainMismatchError";requiredChain;currentChain;constructor(e,r){let n=`Wrong chain. The transaction requires ${e}, but you are connected to ${r}.`;super(n),this.requiredChain=e,this.currentChain=r;}};async function b({tx:t,stopPolling:e,onSuccess:r,onFailure:n,onIntervalTick:o}){if(t.adapter!==orbitCore.OrbitAdapter.SOLANA)throw new Error('Tx adapter is not Solana. Please set the adapter to "solana" in the transaction object.');try{let a=orbitSolana.createSolanaRPC({rpcUrlOrMoniker:t.rpcUrl??orbitSolana.getCluster({cluster:t.chainId})}),s=(await a.getSignatureStatuses([t.txKey]).send())?.value?.[0];if(!s)return;let{fee:u,recentBlockhash:c,instructions:d}=t;if(!u||!c||!d){let P=await a.getTransaction(t.txKey,{encoding:"json",maxSupportedTransactionVersion:0}).send(),{meta:p,transaction:f}=P||{};if(!p||!f)return;u=Number(p.fee??0),c=f.message.recentBlockhash?.toString(),d=f.message.instructions;}let i={...s,slot:Number(s.slot),confirmations:Number(s.confirmations??0),fee:u,recentBlockhash:c,instructions:d};if(o?.(i),i.err){n(i),e({withoutRemoving:!0});return}if(i.confirmationStatus==="finalized"){r(i),e({withoutRemoving:!0});return}m__default.default().diff(m__default.default.unix(t.localTimestamp),"hour")>=1&&(n(i),e());}catch(a){console.error("Error in solanaFetcher:",a),n({err:a}),e();}}async function S({tx:t,onSuccessCallback:e,...r}){return pulsarCore.initializePollingTracker({tx:t,fetcher:b,removeTxFromPool:r.removeTxFromPool,pollingInterval:2500,maxRetries:10,onSuccess:n=>{r.updateTxParams(t.txKey,{status:pulsarCore.TransactionStatus.Success,pending:false,isError:false,finishedTimestamp:m__default.default().unix(),fee:n.fee,instructions:n.instructions,recentBlockhash:n.recentBlockhash,confirmations:"MAX",slot:n.slot});let o=r.transactionsPool[t.txKey];e&&o&&e(o);},onIntervalTick:n=>{r.updateTxParams(t.txKey,{confirmations:n.confirmations??0,slot:n.slot,fee:n.fee,instructions:n.instructions,recentBlockhash:n.recentBlockhash});},onFailure:n=>{let o=n?.err?`Transaction failed: ${JSON.stringify(n.err)}`:"Transaction tracking timed out or the transaction was not found.";r.updateTxParams(t.txKey,{status:pulsarCore.TransactionStatus.Failed,pending:false,isError:true,errorMessage:o,finishedTimestamp:m__default.default().unix()});}})}async function g({tx:t,tracker:e,...r}){switch(e){case pulsarCore.TransactionTracker.Solana:await S({tx:t,...r});break;default:console.error(`Unknown tracker type for Solana adapter: ${e}`),r.updateTxParams(t.txKey,{status:pulsarCore.TransactionStatus.Failed,pending:false,isError:true,errorMessage:`Unsupported tracker type: "${e}"`});break}}var h=(t,e)=>{if(e!==t)throw new l(t,e)};function pr(t){let{rpcUrls:e}=t;return {key:orbitCore.OrbitAdapter.SOLANA,getConnectorInfo:()=>{let r=orbitSolana.getConnectedSolanaConnector();return {walletAddress:orbitCore.lastConnectedConnectorHelpers.getLastConnectedConnector()?.address??r.accounts[0].address??"0x0",connectorType:orbitCore.getConnectorTypeFromName(orbitCore.OrbitAdapter.SOLANA,r.name)}},checkChainForTx:async r=>{if(!orbitSolana.getConnectedSolanaConnector())throw new Error("Wallet not provided. Cannot perform chain check.");try{h(r,orbitCore.lastConnectedConnectorHelpers.getLastConnectedConnector()?.chainId??"");}catch(o){throw o instanceof l?o:new Error(`Chain check failed: ${o instanceof Error?o.message:String(o)}`)}},checkTransactionsTracker:r=>({tracker:pulsarCore.TransactionTracker.Solana,txKey:r}),checkAndInitializeTrackerInStore:({tx:r,...n})=>g({tracker:r.tracker,tx:r,...n}),getExplorerUrl:(r,n)=>orbitSolana.getSolanaExplorerLink(r,n),getExplorerTxUrl:r=>orbitSolana.getSolanaExplorerLink(`/tx/${r.txKey}`,r.chainId),retryTxAction:async({onClose:r,txKey:n,executeTxAction:o,tx:a})=>{r(n);let s=orbitSolana.getAvailableSolanaConnectors().filter(i=>i.accounts.length>0)[0];if(!s||!s.accounts[0].address||s.accounts[0].address==="0x0")throw new Error("Retry failed: A wallet must be connected.");if(!o)throw new Error("Retry failed: executeTxAction function is not provided.");let u=orbitSolana.getCluster({cluster:a?.desiredChainID}),c=a.rpcUrl??orbitSolana.getRpcUrlForCluster({cluster:u,rpcUrls:e});if(!c)throw new Error("Retry failed: Could not determine RPC endpoint for the transaction chain.");let d=orbitSolana.createSolanaClientWithCache({rpcUrlOrMoniker:c,rpcUrls:e});await o({actionFunction:()=>a.actionFunction({client:d,...a.payload}),params:a,defaultTracker:pulsarCore.TransactionTracker.Solana});}}}async function gr({client:t,signer:e,instruction:r}){let{value:n}=await t.rpc.getLatestBlockhash().send(),o=gill.createTransaction({feePayer:e,version:0,latestBlockhash:n,instructions:Array.isArray(r)?r:[r]}),a=await gill.signAndSendTransactionMessageWithSigners(o);return gill.getBase58Decoder().decode(a)}exports.SolanaChainMismatchError=l;exports.checkAndInitializeTrackerInStore=g;exports.checkSolanaChain=h;exports.pulsarSolanaAdapter=pr;exports.signAndSendSolanaTx=gr;exports.solanaFetcher=b;exports.solanaTrackerForStore=S;//# sourceMappingURL=index.js.map
2
- //# sourceMappingURL=index.js.map
1
+ 'use strict';var orbitCore=require('@tuwaio/orbit-core'),orbitSolana=require('@tuwaio/orbit-solana'),pulsarCore=require('@tuwaio/pulsar-core'),m=require('dayjs'),gill=require('gill');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var m__default=/*#__PURE__*/_interopDefault(m);var l=class extends Error{name="SolanaChainMismatchError";requiredChain;currentChain;constructor(e,r){let n=`Wrong chain. The transaction requires ${e}, but you are connected to ${r}.`;super(n),this.requiredChain=e,this.currentChain=r;}};async function b({tx:t,stopPolling:e,onSuccess:r,onFailure:n,onIntervalTick:o}){if(t.adapter!==orbitCore.OrbitAdapter.SOLANA)throw new Error('Tx adapter is not Solana. Please set the adapter to "solana" in the transaction object.');try{let a=orbitSolana.createSolanaRPC({rpcUrlOrMoniker:t.rpcUrl??orbitSolana.getCluster({cluster:t.chainId})}),s=(await a.getSignatureStatuses([t.txKey]).send())?.value?.[0];if(!s)return;let{fee:u,recentBlockhash:c,instructions:d}=t;if(!u||!c||!d){let P=await a.getTransaction(t.txKey,{encoding:"json",maxSupportedTransactionVersion:0}).send(),{meta:p,transaction:f}=P||{};if(!p||!f)return;u=Number(p.fee??0),c=f.message.recentBlockhash?.toString(),d=f.message.instructions;}let i={...s,slot:Number(s.slot),confirmations:Number(s.confirmations??0),fee:u,recentBlockhash:c,instructions:d};if(o?.(i),i.err){n(i),e({withoutRemoving:!0});return}if(i.confirmationStatus==="finalized"){r(i),e({withoutRemoving:!0});return}m__default.default().diff(m__default.default.unix(t.localTimestamp),"hour")>=1&&(n(i),e());}catch(a){console.error("Error in solanaFetcher:",a),n({err:a}),e();}}async function S({tx:t,onSuccessCallback:e,...r}){return pulsarCore.initializePollingTracker({tx:t,fetcher:b,removeTxFromPool:r.removeTxFromPool,pollingInterval:2500,maxRetries:10,onSuccess:n=>{r.updateTxParams(t.txKey,{status:pulsarCore.TransactionStatus.Success,pending:false,isError:false,finishedTimestamp:m__default.default().unix(),fee:n.fee,instructions:n.instructions,recentBlockhash:n.recentBlockhash,confirmations:"MAX",slot:n.slot});let o=r.transactionsPool[t.txKey];e&&o&&e(o);},onIntervalTick:n=>{r.updateTxParams(t.txKey,{confirmations:n.confirmations??0,slot:n.slot,fee:n.fee,instructions:n.instructions,recentBlockhash:n.recentBlockhash});},onFailure:n=>{let o=n?.err?`Transaction failed: ${JSON.stringify(n.err)}`:"Transaction tracking timed out or the transaction was not found.";r.updateTxParams(t.txKey,{status:pulsarCore.TransactionStatus.Failed,pending:false,isError:true,errorMessage:o,finishedTimestamp:m__default.default().unix()});}})}async function g({tx:t,tracker:e,...r}){switch(e){case pulsarCore.TransactionTracker.Solana:await S({tx:t,...r});break;default:console.error(`Unknown tracker type for Solana adapter: ${e}`),r.updateTxParams(t.txKey,{status:pulsarCore.TransactionStatus.Failed,pending:false,isError:true,errorMessage:`Unsupported tracker type: "${e}"`});break}}var h=(t,e)=>{if(e!==t)throw new l(t,e)};function pr(t){let{rpcUrls:e}=t;return {key:orbitCore.OrbitAdapter.SOLANA,getConnectorInfo:()=>{let r=orbitSolana.getConnectedSolanaConnector();return {walletAddress:orbitCore.lastConnectedConnectorHelpers.getLastConnectedConnector()?.address??r.accounts[0].address??"0x0",connectorType:orbitCore.getConnectorTypeFromName(orbitCore.OrbitAdapter.SOLANA,r.name)}},checkChainForTx:async r=>{if(!orbitSolana.getConnectedSolanaConnector())throw new Error("Wallet not provided. Cannot perform chain check.");try{h(r,orbitCore.lastConnectedConnectorHelpers.getLastConnectedConnector()?.chainId??"");}catch(o){throw o instanceof l?o:new Error(`Chain check failed: ${o instanceof Error?o.message:String(o)}`)}},checkTransactionsTracker:r=>({tracker:pulsarCore.TransactionTracker.Solana,txKey:r}),checkAndInitializeTrackerInStore:({tx:r,...n})=>g({tracker:r.tracker,tx:r,...n}),getExplorerUrl:(r,n)=>orbitSolana.getSolanaExplorerLink(r,n),getExplorerTxUrl:r=>orbitSolana.getSolanaExplorerLink(`/tx/${r.txKey}`,r.chainId),retryTxAction:async({onClose:r,txKey:n,executeTxAction:o,tx:a})=>{r(n);let s=orbitSolana.getAvailableSolanaConnectors().filter(i=>i.accounts.length>0)[0];if(!s||!s.accounts[0].address||s.accounts[0].address==="0x0")throw new Error("Retry failed: A wallet must be connected.");if(!o)throw new Error("Retry failed: executeTxAction function is not provided.");let u=orbitSolana.getCluster({cluster:a?.desiredChainID}),c=a.rpcUrl??orbitSolana.getRpcUrlForCluster({cluster:u,rpcUrls:e});if(!c)throw new Error("Retry failed: Could not determine RPC endpoint for the transaction chain.");let d=orbitSolana.createSolanaClientWithCache({rpcUrlOrMoniker:c,rpcUrls:e});await o({actionFunction:()=>a.actionFunction({client:d,...a.payload}),params:a,defaultTracker:pulsarCore.TransactionTracker.Solana});}}}async function gr({client:t,signer:e,instruction:r}){let{value:n}=await t.rpc.getLatestBlockhash().send(),o=gill.createTransaction({feePayer:e,version:0,latestBlockhash:n,instructions:Array.isArray(r)?r:[r]}),a=await gill.signAndSendTransactionMessageWithSigners(o);return gill.getBase58Decoder().decode(a)}exports.SolanaChainMismatchError=l;exports.checkAndInitializeTrackerInStore=g;exports.checkSolanaChain=h;exports.pulsarSolanaAdapter=pr;exports.signAndSendSolanaTx=gr;exports.solanaFetcher=b;exports.solanaTrackerForStore=S;
package/dist/index.mjs CHANGED
@@ -1,2 +1 @@
1
- import {OrbitAdapter,lastConnectedConnectorHelpers,getConnectorTypeFromName}from'@tuwaio/orbit-core';import {createSolanaRPC,getCluster,getSolanaExplorerLink,getAvailableSolanaConnectors,getRpcUrlForCluster,createSolanaClientWithCache,getConnectedSolanaConnector}from'@tuwaio/orbit-solana';import {initializePollingTracker,TransactionStatus,TransactionTracker}from'@tuwaio/pulsar-core';import m from'dayjs';import {createTransaction,signAndSendTransactionMessageWithSigners,getBase58Decoder}from'gill';var l=class extends Error{name="SolanaChainMismatchError";requiredChain;currentChain;constructor(e,r){let n=`Wrong chain. The transaction requires ${e}, but you are connected to ${r}.`;super(n),this.requiredChain=e,this.currentChain=r;}};async function b({tx:t,stopPolling:e,onSuccess:r,onFailure:n,onIntervalTick:o}){if(t.adapter!==OrbitAdapter.SOLANA)throw new Error('Tx adapter is not Solana. Please set the adapter to "solana" in the transaction object.');try{let a=createSolanaRPC({rpcUrlOrMoniker:t.rpcUrl??getCluster({cluster:t.chainId})}),s=(await a.getSignatureStatuses([t.txKey]).send())?.value?.[0];if(!s)return;let{fee:u,recentBlockhash:c,instructions:d}=t;if(!u||!c||!d){let P=await a.getTransaction(t.txKey,{encoding:"json",maxSupportedTransactionVersion:0}).send(),{meta:p,transaction:f}=P||{};if(!p||!f)return;u=Number(p.fee??0),c=f.message.recentBlockhash?.toString(),d=f.message.instructions;}let i={...s,slot:Number(s.slot),confirmations:Number(s.confirmations??0),fee:u,recentBlockhash:c,instructions:d};if(o?.(i),i.err){n(i),e({withoutRemoving:!0});return}if(i.confirmationStatus==="finalized"){r(i),e({withoutRemoving:!0});return}m().diff(m.unix(t.localTimestamp),"hour")>=1&&(n(i),e());}catch(a){console.error("Error in solanaFetcher:",a),n({err:a}),e();}}async function S({tx:t,onSuccessCallback:e,...r}){return initializePollingTracker({tx:t,fetcher:b,removeTxFromPool:r.removeTxFromPool,pollingInterval:2500,maxRetries:10,onSuccess:n=>{r.updateTxParams(t.txKey,{status:TransactionStatus.Success,pending:false,isError:false,finishedTimestamp:m().unix(),fee:n.fee,instructions:n.instructions,recentBlockhash:n.recentBlockhash,confirmations:"MAX",slot:n.slot});let o=r.transactionsPool[t.txKey];e&&o&&e(o);},onIntervalTick:n=>{r.updateTxParams(t.txKey,{confirmations:n.confirmations??0,slot:n.slot,fee:n.fee,instructions:n.instructions,recentBlockhash:n.recentBlockhash});},onFailure:n=>{let o=n?.err?`Transaction failed: ${JSON.stringify(n.err)}`:"Transaction tracking timed out or the transaction was not found.";r.updateTxParams(t.txKey,{status:TransactionStatus.Failed,pending:false,isError:true,errorMessage:o,finishedTimestamp:m().unix()});}})}async function g({tx:t,tracker:e,...r}){switch(e){case TransactionTracker.Solana:await S({tx:t,...r});break;default:console.error(`Unknown tracker type for Solana adapter: ${e}`),r.updateTxParams(t.txKey,{status:TransactionStatus.Failed,pending:false,isError:true,errorMessage:`Unsupported tracker type: "${e}"`});break}}var h=(t,e)=>{if(e!==t)throw new l(t,e)};function pr(t){let{rpcUrls:e}=t;return {key:OrbitAdapter.SOLANA,getConnectorInfo:()=>{let r=getConnectedSolanaConnector();return {walletAddress:lastConnectedConnectorHelpers.getLastConnectedConnector()?.address??r.accounts[0].address??"0x0",connectorType:getConnectorTypeFromName(OrbitAdapter.SOLANA,r.name)}},checkChainForTx:async r=>{if(!getConnectedSolanaConnector())throw new Error("Wallet not provided. Cannot perform chain check.");try{h(r,lastConnectedConnectorHelpers.getLastConnectedConnector()?.chainId??"");}catch(o){throw o instanceof l?o:new Error(`Chain check failed: ${o instanceof Error?o.message:String(o)}`)}},checkTransactionsTracker:r=>({tracker:TransactionTracker.Solana,txKey:r}),checkAndInitializeTrackerInStore:({tx:r,...n})=>g({tracker:r.tracker,tx:r,...n}),getExplorerUrl:(r,n)=>getSolanaExplorerLink(r,n),getExplorerTxUrl:r=>getSolanaExplorerLink(`/tx/${r.txKey}`,r.chainId),retryTxAction:async({onClose:r,txKey:n,executeTxAction:o,tx:a})=>{r(n);let s=getAvailableSolanaConnectors().filter(i=>i.accounts.length>0)[0];if(!s||!s.accounts[0].address||s.accounts[0].address==="0x0")throw new Error("Retry failed: A wallet must be connected.");if(!o)throw new Error("Retry failed: executeTxAction function is not provided.");let u=getCluster({cluster:a?.desiredChainID}),c=a.rpcUrl??getRpcUrlForCluster({cluster:u,rpcUrls:e});if(!c)throw new Error("Retry failed: Could not determine RPC endpoint for the transaction chain.");let d=createSolanaClientWithCache({rpcUrlOrMoniker:c,rpcUrls:e});await o({actionFunction:()=>a.actionFunction({client:d,...a.payload}),params:a,defaultTracker:TransactionTracker.Solana});}}}async function gr({client:t,signer:e,instruction:r}){let{value:n}=await t.rpc.getLatestBlockhash().send(),o=createTransaction({feePayer:e,version:0,latestBlockhash:n,instructions:Array.isArray(r)?r:[r]}),a=await signAndSendTransactionMessageWithSigners(o);return getBase58Decoder().decode(a)}export{l as SolanaChainMismatchError,g as checkAndInitializeTrackerInStore,h as checkSolanaChain,pr as pulsarSolanaAdapter,gr as signAndSendSolanaTx,b as solanaFetcher,S as solanaTrackerForStore};//# sourceMappingURL=index.mjs.map
2
- //# sourceMappingURL=index.mjs.map
1
+ import {OrbitAdapter,lastConnectedConnectorHelpers,getConnectorTypeFromName}from'@tuwaio/orbit-core';import {createSolanaRPC,getCluster,getSolanaExplorerLink,getAvailableSolanaConnectors,getRpcUrlForCluster,createSolanaClientWithCache,getConnectedSolanaConnector}from'@tuwaio/orbit-solana';import {initializePollingTracker,TransactionStatus,TransactionTracker}from'@tuwaio/pulsar-core';import m from'dayjs';import {createTransaction,signAndSendTransactionMessageWithSigners,getBase58Decoder}from'gill';var l=class extends Error{name="SolanaChainMismatchError";requiredChain;currentChain;constructor(e,r){let n=`Wrong chain. The transaction requires ${e}, but you are connected to ${r}.`;super(n),this.requiredChain=e,this.currentChain=r;}};async function b({tx:t,stopPolling:e,onSuccess:r,onFailure:n,onIntervalTick:o}){if(t.adapter!==OrbitAdapter.SOLANA)throw new Error('Tx adapter is not Solana. Please set the adapter to "solana" in the transaction object.');try{let a=createSolanaRPC({rpcUrlOrMoniker:t.rpcUrl??getCluster({cluster:t.chainId})}),s=(await a.getSignatureStatuses([t.txKey]).send())?.value?.[0];if(!s)return;let{fee:u,recentBlockhash:c,instructions:d}=t;if(!u||!c||!d){let P=await a.getTransaction(t.txKey,{encoding:"json",maxSupportedTransactionVersion:0}).send(),{meta:p,transaction:f}=P||{};if(!p||!f)return;u=Number(p.fee??0),c=f.message.recentBlockhash?.toString(),d=f.message.instructions;}let i={...s,slot:Number(s.slot),confirmations:Number(s.confirmations??0),fee:u,recentBlockhash:c,instructions:d};if(o?.(i),i.err){n(i),e({withoutRemoving:!0});return}if(i.confirmationStatus==="finalized"){r(i),e({withoutRemoving:!0});return}m().diff(m.unix(t.localTimestamp),"hour")>=1&&(n(i),e());}catch(a){console.error("Error in solanaFetcher:",a),n({err:a}),e();}}async function S({tx:t,onSuccessCallback:e,...r}){return initializePollingTracker({tx:t,fetcher:b,removeTxFromPool:r.removeTxFromPool,pollingInterval:2500,maxRetries:10,onSuccess:n=>{r.updateTxParams(t.txKey,{status:TransactionStatus.Success,pending:false,isError:false,finishedTimestamp:m().unix(),fee:n.fee,instructions:n.instructions,recentBlockhash:n.recentBlockhash,confirmations:"MAX",slot:n.slot});let o=r.transactionsPool[t.txKey];e&&o&&e(o);},onIntervalTick:n=>{r.updateTxParams(t.txKey,{confirmations:n.confirmations??0,slot:n.slot,fee:n.fee,instructions:n.instructions,recentBlockhash:n.recentBlockhash});},onFailure:n=>{let o=n?.err?`Transaction failed: ${JSON.stringify(n.err)}`:"Transaction tracking timed out or the transaction was not found.";r.updateTxParams(t.txKey,{status:TransactionStatus.Failed,pending:false,isError:true,errorMessage:o,finishedTimestamp:m().unix()});}})}async function g({tx:t,tracker:e,...r}){switch(e){case TransactionTracker.Solana:await S({tx:t,...r});break;default:console.error(`Unknown tracker type for Solana adapter: ${e}`),r.updateTxParams(t.txKey,{status:TransactionStatus.Failed,pending:false,isError:true,errorMessage:`Unsupported tracker type: "${e}"`});break}}var h=(t,e)=>{if(e!==t)throw new l(t,e)};function pr(t){let{rpcUrls:e}=t;return {key:OrbitAdapter.SOLANA,getConnectorInfo:()=>{let r=getConnectedSolanaConnector();return {walletAddress:lastConnectedConnectorHelpers.getLastConnectedConnector()?.address??r.accounts[0].address??"0x0",connectorType:getConnectorTypeFromName(OrbitAdapter.SOLANA,r.name)}},checkChainForTx:async r=>{if(!getConnectedSolanaConnector())throw new Error("Wallet not provided. Cannot perform chain check.");try{h(r,lastConnectedConnectorHelpers.getLastConnectedConnector()?.chainId??"");}catch(o){throw o instanceof l?o:new Error(`Chain check failed: ${o instanceof Error?o.message:String(o)}`)}},checkTransactionsTracker:r=>({tracker:TransactionTracker.Solana,txKey:r}),checkAndInitializeTrackerInStore:({tx:r,...n})=>g({tracker:r.tracker,tx:r,...n}),getExplorerUrl:(r,n)=>getSolanaExplorerLink(r,n),getExplorerTxUrl:r=>getSolanaExplorerLink(`/tx/${r.txKey}`,r.chainId),retryTxAction:async({onClose:r,txKey:n,executeTxAction:o,tx:a})=>{r(n);let s=getAvailableSolanaConnectors().filter(i=>i.accounts.length>0)[0];if(!s||!s.accounts[0].address||s.accounts[0].address==="0x0")throw new Error("Retry failed: A wallet must be connected.");if(!o)throw new Error("Retry failed: executeTxAction function is not provided.");let u=getCluster({cluster:a?.desiredChainID}),c=a.rpcUrl??getRpcUrlForCluster({cluster:u,rpcUrls:e});if(!c)throw new Error("Retry failed: Could not determine RPC endpoint for the transaction chain.");let d=createSolanaClientWithCache({rpcUrlOrMoniker:c,rpcUrls:e});await o({actionFunction:()=>a.actionFunction({client:d,...a.payload}),params:a,defaultTracker:TransactionTracker.Solana});}}}async function gr({client:t,signer:e,instruction:r}){let{value:n}=await t.rpc.getLatestBlockhash().send(),o=createTransaction({feePayer:e,version:0,latestBlockhash:n,instructions:Array.isArray(r)?r:[r]}),a=await signAndSendTransactionMessageWithSigners(o);return getBase58Decoder().decode(a)}export{l as SolanaChainMismatchError,g as checkAndInitializeTrackerInStore,h as checkSolanaChain,pr as pulsarSolanaAdapter,gr as signAndSendSolanaTx,b as solanaFetcher,S as solanaTrackerForStore};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuwaio/pulsar-solana",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "private": false,
5
5
  "author": "Oleksandr Tkach",
6
6
  "license": "Apache-2.0",
@@ -50,20 +50,20 @@
50
50
  "zustand": "5.x.x"
51
51
  },
52
52
  "devDependencies": {
53
- "@tuwaio/orbit-core": "^0.2.1",
54
- "@tuwaio/orbit-solana": "^0.2.1",
53
+ "@tuwaio/orbit-core": "^0.2.4",
54
+ "@tuwaio/orbit-solana": "^0.2.2",
55
55
  "@wallet-standard/app": "^1.1.0",
56
56
  "@wallet-standard/ui-core": "^1.0.0",
57
57
  "@wallet-standard/ui-registry": "^1.0.1",
58
58
  "dayjs": "^1.11.19",
59
59
  "gill": "^0.14.0",
60
- "immer": "^11.1.0",
60
+ "immer": "^11.1.3",
61
61
  "jsdom": "^27.4.0",
62
62
  "tsup": "^8.5.1",
63
63
  "typescript": "^5.9.3",
64
- "vitest": "^4.0.16",
65
- "zustand": "^5.0.9",
66
- "@tuwaio/pulsar-core": "^0.3.1"
64
+ "vitest": "^4.0.17",
65
+ "zustand": "^5.0.10",
66
+ "@tuwaio/pulsar-core": "^0.3.3"
67
67
  },
68
68
  "scripts": {
69
69
  "start": "tsup src/index.ts --watch",
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/trackers/solanaTracker.ts","../src/utils/checkAndInitializeTrackerInStore.ts","../src/utils/checkSolanaChain.ts","../src/adapters/solanaAdapter.ts","../src/utils/signAndSendSolanaTx.ts"],"names":["SolanaChainMismatchError","requiredChain","currentChain","message","solanaFetcher","tx","stopPolling","onSuccess","onFailure","onIntervalTick","OrbitAdapter","rpc","createSolanaRPC","getCluster","status","fee","recentBlockhash","instructions","txDetails","meta","transaction","typedStatus","dayjs","error","solanaTrackerForStore","onSuccessCallback","rest","initializePollingTracker","response","TransactionStatus","updatedTx","errorMessage","checkAndInitializeTrackerInStore","tracker","TransactionTracker","checkSolanaChain","pulsarSolanaAdapter","config","rpcUrls","connectedConnector","getConnectedSolanaConnector","lastConnectedConnectorHelpers","getConnectorTypeFromName","txChain","e","actionTxKey","url","chainId","getSolanaExplorerLink","onClose","txKey","executeTxAction","getAvailableSolanaConnectors","connector","clusterForRetry","rpcUrlForRetry","getRpcUrlForCluster","client","createSolanaClientWithCache","signAndSendSolanaTx","signer","instruction","latestBlockhash","createTransaction","signature","signAndSendTransactionMessageWithSigners","getBase58Decoder"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @file This file defines custom error classes for the @tuwaio/pulsar-solana package.\n */\n\n/**\n * Thrown when the connected Solana chain does not match the required chain for a transaction.\n *\n * This allows consuming applications to `catch` this specific error and\n * implement custom logic, such as prompting the user to switch networks.\n */\nexport class SolanaChainMismatchError extends Error {\n /** The name of the error, for easy identification. */\n name = 'SolanaChainMismatchError';\n /** The chain that the transaction requires (e.g., 'solana:mainnet'). */\n requiredChain: string;\n /** The chain the wallet is currently connected to. */\n currentChain: string;\n\n constructor(requiredChain: string, currentChain: string) {\n const message = `Wrong chain. The transaction requires ${requiredChain}, but you are connected to ${currentChain}.`;\n super(message);\n this.requiredChain = requiredChain;\n this.currentChain = currentChain;\n }\n}\n","/**\n * @file Implements the transaction tracking logic for Solana transactions.\n * It integrates with the Pulsar store and uses a polling mechanism to query the\n * `getSignatureStatuses` RPC method for updates on transaction status.\n */\n\nimport { OrbitAdapter } from '@tuwaio/orbit-core';\nimport { createSolanaRPC, getCluster } from '@tuwaio/orbit-solana';\nimport {\n initializePollingTracker,\n ITxTrackingStore,\n OnSuccessCallback,\n PollingTrackerConfig,\n Transaction,\n TransactionStatus,\n} from '@tuwaio/pulsar-core';\nimport dayjs from 'dayjs';\nimport { Signature, TransactionError } from 'gill';\n\n/**\n * @typedef SolanaSignatureStatusResponse\n * Represents the status of a Solana transaction and includes additional metadata.\n *\n * @property {number} slot - The slot in which the transaction was processed.\n * @property {number | null} confirmations - The number of confirmations received.\n * @property {TransactionError | null} err - The error, if any, associated with the transaction.\n * @property {'processed' | 'confirmed' | 'finalized' | null} confirmationStatus - The status of the transaction's confirmation.\n * @property {number} [fee] - The transaction fee in lamports.\n * @property {string} [recentBlockhash] - The blockhash used for the transaction.\n * @property {unknown[]} [instructions] - The instructions included in the transaction.\n */\ntype SolanaSignatureStatusResponse = {\n slot: number;\n confirmations: number | null;\n err: TransactionError | null;\n confirmationStatus: 'processed' | 'confirmed' | 'finalized' | null;\n fee?: number;\n recentBlockhash?: string;\n instructions?: unknown[];\n};\n\n/**\n * @typedef SolanaFetcherParams\n * Parameters used for the Solana fetcher function.\n */\ntype SolanaFetcherParams = Parameters<PollingTrackerConfig<SolanaSignatureStatusResponse, Transaction>['fetcher']>[0];\n\n/**\n * Fetches and tracks Solana transactions using the `getSignatureStatuses` RPC method.\n * Transaction details (`getTransaction`) are only fetched once, if not already present in the transaction object.\n *\n * @param {SolanaFetcherParams} params - The fetcher parameters, automatically provided by the tracker.\n * @throws Will throw an error if the transaction adapter is not set to Solana.\n * @returns {Promise<void>} Resolves when the fetcher completes execution for the current polling cycle.\n */\nexport async function solanaFetcher({\n tx,\n stopPolling,\n onSuccess,\n onFailure,\n onIntervalTick,\n}: SolanaFetcherParams): Promise<void> {\n // Validate that the transaction uses the Solana adapter\n if (tx.adapter !== OrbitAdapter.SOLANA) {\n throw new Error('Tx adapter is not Solana. Please set the adapter to \"solana\" in the transaction object.');\n }\n\n try {\n // Initialize the Solana RPC client\n const rpc = createSolanaRPC({ rpcUrlOrMoniker: tx.rpcUrl ?? getCluster({ cluster: tx.chainId as string }) });\n\n // Fetch transaction signature status\n const statuses = await rpc.getSignatureStatuses([tx.txKey as Signature]).send();\n const status = statuses?.value?.[0];\n\n // Skip further processing if no status is found\n if (!status) {\n return;\n }\n\n // Extract or fetch transaction details only when missing\n let { fee, recentBlockhash, instructions } = tx;\n\n if (!fee || !recentBlockhash || !instructions) {\n const txDetails = await rpc\n .getTransaction(tx.txKey as Signature, { encoding: 'json', maxSupportedTransactionVersion: 0 })\n .send();\n const { meta, transaction } = txDetails || {};\n\n // If no transaction details are found, skip further processing\n if (!meta || !transaction) {\n return;\n }\n\n // Extract details from RPC response\n fee = Number(meta.fee ?? 0);\n recentBlockhash = transaction.message.recentBlockhash?.toString();\n instructions = transaction.message.instructions as unknown[];\n }\n\n // Construct the extended transaction status object\n const typedStatus: SolanaSignatureStatusResponse = {\n ...status,\n slot: Number(status.slot),\n confirmations: Number(status.confirmations ?? 0),\n fee,\n recentBlockhash,\n instructions,\n };\n\n // Trigger periodic updates for transaction tracking\n onIntervalTick?.(typedStatus);\n\n // Handle transaction error state\n if (typedStatus.err) {\n onFailure(typedStatus);\n stopPolling({ withoutRemoving: true });\n return;\n }\n\n // Handle finalized transaction state\n if (typedStatus.confirmationStatus === 'finalized') {\n onSuccess(typedStatus);\n stopPolling({ withoutRemoving: true });\n return;\n }\n\n // Stop polling if the transaction is unconfirmed for more than 1 hour\n const elapsedDays = dayjs().diff(dayjs.unix(tx.localTimestamp), 'hour');\n if (elapsedDays >= 1) {\n onFailure(typedStatus);\n stopPolling();\n }\n } catch (error) {\n console.error('Error in solanaFetcher:', error);\n onFailure({ err: error } as SolanaSignatureStatusResponse);\n stopPolling();\n }\n}\n\n/**\n * A higher-level tracker that integrates the Solana polling logic with the Pulsar store.\n *\n * @template T - The application-specific Solana transaction type.\n *\n * @param {object} params - Parameters to connect the Solana tracker with the store.\n * @param {T} params.tx - The Solana transaction being tracked.\n * @param {Function} params.updateTxParams - A callback to update specific fields of a transaction in the store.\n * @param {Function} [params.removeTxFromPool] - A function to remove a completed or canceled transaction from the store.\n * @returns {Promise<void>} Resolves when the tracker is successfully initialized.\n */\nexport async function solanaTrackerForStore<T extends Transaction>({\n tx,\n onSuccessCallback,\n ...rest\n}: Pick<ITxTrackingStore<T>, 'updateTxParams' | 'removeTxFromPool' | 'transactionsPool'> & {\n tx: T;\n} & OnSuccessCallback<T>): Promise<void> {\n return initializePollingTracker<SolanaSignatureStatusResponse, T>({\n tx,\n fetcher: solanaFetcher,\n removeTxFromPool: rest.removeTxFromPool,\n pollingInterval: 2500, // Polling interval: 2.5 seconds\n maxRetries: 10, // Max retries: 10 times\n\n /**\n * Success handler - updates the Pulsar store with finalized transaction details.\n *\n * @param {SolanaSignatureStatusResponse} response - The finalized transaction details.\n */\n onSuccess: (response) => {\n rest.updateTxParams(tx.txKey, {\n status: TransactionStatus.Success,\n pending: false,\n isError: false,\n finishedTimestamp: dayjs().unix(),\n fee: response.fee,\n instructions: response.instructions,\n recentBlockhash: response.recentBlockhash,\n confirmations: 'MAX',\n slot: response.slot,\n });\n\n // Trigger global success callbacks, if applicable\n const updatedTx = rest.transactionsPool[tx.txKey];\n if (onSuccessCallback && updatedTx) {\n onSuccessCallback(updatedTx);\n }\n },\n\n /**\n * Interval handler - updates interim transaction details in the store.\n *\n * @param {SolanaSignatureStatusResponse} response - The latest transaction status update.\n */\n onIntervalTick: (response) => {\n rest.updateTxParams(tx.txKey, {\n confirmations: response.confirmations ?? 0,\n slot: response.slot,\n fee: response.fee,\n instructions: response.instructions,\n recentBlockhash: response.recentBlockhash,\n });\n },\n\n /**\n * Failure handler - updates the store when the transaction fails or times out.\n *\n * @param {SolanaSignatureStatusResponse} response - The failure response details.\n */\n onFailure: (response) => {\n const errorMessage = response?.err\n ? `Transaction failed: ${JSON.stringify(response.err)}`\n : 'Transaction tracking timed out or the transaction was not found.';\n rest.updateTxParams(tx.txKey, {\n status: TransactionStatus.Failed,\n pending: false,\n isError: true,\n errorMessage,\n finishedTimestamp: dayjs().unix(),\n });\n },\n });\n}\n","/**\n * @file This file contains the primary router for initializing transaction trackers.\n */\n\nimport {\n ITxTrackingStore,\n OnSuccessCallback,\n Transaction,\n TransactionStatus,\n TransactionTracker,\n} from '@tuwaio/pulsar-core';\n\nimport { solanaTrackerForStore } from '../trackers/solanaTracker';\n\n/**\n * Initializes the correct background tracker for a given Solana transaction.\n * This function acts as a router, selecting the appropriate tracker based on the `tx.tracker` property.\n *\n * @template T - The transaction type.\n * @param {object} params - The parameters for initializing the tracker.\n * @param {T} params.tx - The transaction object to be tracked.\n * @param {TransactionTracker} params.tracker - The specific tracker to use.\n * @param {object} params.rest - The rest of the store's methods and state needed by the tracker.\n * @returns {Promise<void>} A promise that resolves when the tracker has been initialized.\n */\nexport async function checkAndInitializeTrackerInStore<T extends Transaction>({\n tx,\n tracker,\n ...rest\n}: {\n tx: T;\n tracker: TransactionTracker;\n} & OnSuccessCallback<T> &\n Pick<ITxTrackingStore<T>, 'updateTxParams' | 'removeTxFromPool' | 'transactionsPool'>): Promise<void> {\n switch (tracker) {\n case TransactionTracker.Solana:\n await solanaTrackerForStore({\n tx,\n ...rest,\n });\n break;\n default:\n console.error(`Unknown tracker type for Solana adapter: ${tracker}`);\n // If an unsupported tracker is specified, mark the transaction as failed.\n rest.updateTxParams(tx.txKey, {\n status: TransactionStatus.Failed,\n pending: false,\n isError: true,\n errorMessage: `Unsupported tracker type: \"${tracker}\"`,\n });\n break;\n }\n}\n","/**\n * @file This file contains a utility to verify the connected Solana chain.\n */\n\nimport { SolanaChainMismatchError } from '../errors';\n\n/**\n * Checks if the wallet's current chain matches the required chain for a transaction.\n * This function compares the `chain` property from the Wallet Standard account object\n * with the required chain identifier (e.g., 'solana:mainnet').\n *\n * @param {string} requiredChain - The chain identifier that the transaction requires.\n * @param {string} currentChain - The chain identifier the wallet is currently connected to.\n * @throws {SolanaChainMismatchError} If the connected chain does not match the required chain.\n */\nexport const checkSolanaChain = (requiredChain: string, currentChain: string): void => {\n if (currentChain !== requiredChain) {\n throw new SolanaChainMismatchError(requiredChain, currentChain);\n }\n};\n","/**\n * @file This file contains the factory function for creating the Solana adapter for Pulsar.\n */\n\nimport { getConnectorTypeFromName, lastConnectedConnectorHelpers, OrbitAdapter } from '@tuwaio/orbit-core';\nimport {\n createSolanaClientWithCache,\n getAvailableSolanaConnectors,\n getCluster,\n getConnectedSolanaConnector,\n getRpcUrlForCluster,\n getSolanaExplorerLink,\n} from '@tuwaio/orbit-solana';\nimport { Transaction, TransactionTracker, TxAdapter } from '@tuwaio/pulsar-core';\nimport { SolanaClusterMoniker } from 'gill';\n\nimport { SolanaChainMismatchError } from '../errors';\nimport { SolanaAdapterConfig } from '../types';\nimport { checkAndInitializeTrackerInStore } from '../utils/checkAndInitializeTrackerInStore';\nimport { checkSolanaChain } from '../utils/checkSolanaChain';\n\n/**\n * Creates a Solana adapter for the Pulsar transaction tracking engine.\n * This factory function produces a wallet-library-agnostic adapter that can be\n * configured for multiple Solana clusters (e.g., mainnet-beta, devnet) and\n * can operate even without a connected wallet for read-only tasks.\n *\n * @template T - The application-specific transaction type.\n * @param {SolanaAdapterConfig} config - The configuration object for the adapter.\n * @returns {TxAdapter<T>} The configured Solana transaction adapter.\n *\n * @throws {Error} Throws an error if the wagmi `config` is not provided.\n */\nexport function pulsarSolanaAdapter<T extends Transaction>(config: SolanaAdapterConfig): TxAdapter<T> {\n const { rpcUrls } = config;\n\n return {\n key: OrbitAdapter.SOLANA,\n\n getConnectorInfo: () => {\n const connectedConnector = getConnectedSolanaConnector();\n const localConnectedConnector = lastConnectedConnectorHelpers.getLastConnectedConnector();\n return {\n walletAddress: localConnectedConnector?.address ?? connectedConnector.accounts[0].address ?? '0x0',\n connectorType: getConnectorTypeFromName(OrbitAdapter.SOLANA, connectedConnector.name),\n };\n },\n\n checkChainForTx: async (txChain) => {\n const connectedConnector = getConnectedSolanaConnector();\n if (!connectedConnector) {\n throw new Error('Wallet not provided. Cannot perform chain check.');\n }\n try {\n checkSolanaChain(\n txChain as string,\n (lastConnectedConnectorHelpers.getLastConnectedConnector()?.chainId as string) ?? '',\n );\n } catch (e) {\n if (e instanceof SolanaChainMismatchError) throw e;\n throw new Error(`Chain check failed: ${e instanceof Error ? e.message : String(e)}`);\n }\n },\n\n checkTransactionsTracker: (actionTxKey) => ({\n tracker: TransactionTracker.Solana,\n txKey: actionTxKey as string,\n }),\n\n checkAndInitializeTrackerInStore: ({ tx, ...rest }) => {\n return checkAndInitializeTrackerInStore({\n tracker: tx.tracker,\n tx,\n ...rest,\n });\n },\n\n getExplorerUrl: (url, chainId) => {\n return getSolanaExplorerLink(url, chainId);\n },\n getExplorerTxUrl: (tx) => {\n return getSolanaExplorerLink(`/tx/${tx.txKey}`, tx.chainId);\n },\n\n retryTxAction: async ({ onClose, txKey, executeTxAction, tx }) => {\n onClose(txKey);\n\n const connectors = getAvailableSolanaConnectors();\n const connectedConnector = connectors.filter((connector) => connector.accounts.length > 0)[0];\n\n if (!connectedConnector || !connectedConnector.accounts[0].address || connectedConnector.accounts[0].address === '0x0') {\n throw new Error('Retry failed: A wallet must be connected.');\n }\n if (!executeTxAction) {\n throw new Error('Retry failed: executeTxAction function is not provided.');\n }\n\n const clusterForRetry = getCluster({ cluster: tx?.desiredChainID as string }) as SolanaClusterMoniker;\n const rpcUrlForRetry = tx.rpcUrl ?? getRpcUrlForCluster({ cluster: clusterForRetry, rpcUrls });\n\n if (!rpcUrlForRetry) {\n throw new Error('Retry failed: Could not determine RPC endpoint for the transaction chain.');\n }\n\n const client = createSolanaClientWithCache({ rpcUrlOrMoniker: rpcUrlForRetry, rpcUrls });\n\n await executeTxAction({\n actionFunction: () =>\n tx.actionFunction({\n client,\n ...tx.payload,\n }),\n params: tx,\n defaultTracker: TransactionTracker.Solana,\n });\n },\n };\n}\n","/**\n * @file This file contains a utility function for signing and sending Solana transactions.\n * It simplifies the process of creating, signing, and broadcasting a transaction to the network.\n */\n\nimport type { Instruction, SolanaClient, TransactionSendingSigner } from 'gill';\nimport { createTransaction, getBase58Decoder, signAndSendTransactionMessageWithSigners } from 'gill';\n\n/**\n * Creates, signs, and sends a Solana transaction with one or more instructions.\n *\n * This async function orchestrates the common flow for broadcasting a transaction:\n * 1. Fetches the latest blockhash from the RPC.\n * 2. Creates a versioned transaction (`v0`).\n * 3. Signs the transaction with the provided signer.\n * 4. Sends the transaction to the network.\n * 5. Decodes and returns the resulting transaction signature.\n *\n * @param {object} params - The parameters for signing and sending the transaction.\n * @param {SolanaClient} params.client - The Solana client instance for RPC communication.\n * @param {TransactionSendingSigner} params.signer - The signer (e.g., a wallet) responsible for signing the transaction.\n * @param {Instruction | Instruction[]} params.instruction - A single instruction or an array of instructions to include in the transaction.\n * @returns A promise that resolves to the transaction signature.\n * @throws Will throw an error if any of the async operations (fetching blockhash, signing, sending) fail.\n *\n * @example\n * const signature = await signAndSendSolanaTx({\n * client: mySolanaClient,\n * signer: wallet,\n * instruction: myTransferInstruction,\n * });\n * console.log('Transaction sent with signature:', signature);\n */\nexport async function signAndSendSolanaTx({\n client,\n signer,\n instruction,\n}: {\n client: SolanaClient;\n signer: TransactionSendingSigner;\n instruction: Instruction | Instruction[];\n}) {\n // 1. Fetch the latest blockhash to ensure transaction validity.\n const { value: latestBlockhash } = await client.rpc.getLatestBlockhash().send();\n\n // 2. Create a version 0 transaction, which is the current standard.\n const transaction = createTransaction({\n feePayer: signer,\n version: 0,\n latestBlockhash,\n instructions: Array.isArray(instruction) ? instruction : [instruction],\n });\n\n // 3. Sign the transaction message and send it to the network.\n const signature = await signAndSendTransactionMessageWithSigners(transaction);\n\n // 4. Decode the resulting signature into the final format.\n return getBase58Decoder().decode(signature);\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/trackers/solanaTracker.ts","../src/utils/checkAndInitializeTrackerInStore.ts","../src/utils/checkSolanaChain.ts","../src/adapters/solanaAdapter.ts","../src/utils/signAndSendSolanaTx.ts"],"names":["SolanaChainMismatchError","requiredChain","currentChain","message","solanaFetcher","tx","stopPolling","onSuccess","onFailure","onIntervalTick","OrbitAdapter","rpc","createSolanaRPC","getCluster","status","fee","recentBlockhash","instructions","txDetails","meta","transaction","typedStatus","dayjs","error","solanaTrackerForStore","onSuccessCallback","rest","initializePollingTracker","response","TransactionStatus","updatedTx","errorMessage","checkAndInitializeTrackerInStore","tracker","TransactionTracker","checkSolanaChain","pulsarSolanaAdapter","config","rpcUrls","connectedConnector","getConnectedSolanaConnector","lastConnectedConnectorHelpers","getConnectorTypeFromName","txChain","e","actionTxKey","url","chainId","getSolanaExplorerLink","onClose","txKey","executeTxAction","getAvailableSolanaConnectors","connector","clusterForRetry","rpcUrlForRetry","getRpcUrlForCluster","client","createSolanaClientWithCache","signAndSendSolanaTx","signer","instruction","latestBlockhash","createTransaction","signature","signAndSendTransactionMessageWithSigners","getBase58Decoder"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * @file This file defines custom error classes for the @tuwaio/pulsar-solana package.\n */\n\n/**\n * Thrown when the connected Solana chain does not match the required chain for a transaction.\n *\n * This allows consuming applications to `catch` this specific error and\n * implement custom logic, such as prompting the user to switch networks.\n */\nexport class SolanaChainMismatchError extends Error {\n /** The name of the error, for easy identification. */\n name = 'SolanaChainMismatchError';\n /** The chain that the transaction requires (e.g., 'solana:mainnet'). */\n requiredChain: string;\n /** The chain the wallet is currently connected to. */\n currentChain: string;\n\n constructor(requiredChain: string, currentChain: string) {\n const message = `Wrong chain. The transaction requires ${requiredChain}, but you are connected to ${currentChain}.`;\n super(message);\n this.requiredChain = requiredChain;\n this.currentChain = currentChain;\n }\n}\n","/**\n * @file Implements the transaction tracking logic for Solana transactions.\n * It integrates with the Pulsar store and uses a polling mechanism to query the\n * `getSignatureStatuses` RPC method for updates on transaction status.\n */\n\nimport { OrbitAdapter } from '@tuwaio/orbit-core';\nimport { createSolanaRPC, getCluster } from '@tuwaio/orbit-solana';\nimport {\n initializePollingTracker,\n ITxTrackingStore,\n OnSuccessCallback,\n PollingTrackerConfig,\n Transaction,\n TransactionStatus,\n} from '@tuwaio/pulsar-core';\nimport dayjs from 'dayjs';\nimport { Signature, TransactionError } from 'gill';\n\n/**\n * @typedef SolanaSignatureStatusResponse\n * Represents the status of a Solana transaction and includes additional metadata.\n *\n * @property {number} slot - The slot in which the transaction was processed.\n * @property {number | null} confirmations - The number of confirmations received.\n * @property {TransactionError | null} err - The error, if any, associated with the transaction.\n * @property {'processed' | 'confirmed' | 'finalized' | null} confirmationStatus - The status of the transaction's confirmation.\n * @property {number} [fee] - The transaction fee in lamports.\n * @property {string} [recentBlockhash] - The blockhash used for the transaction.\n * @property {unknown[]} [instructions] - The instructions included in the transaction.\n */\ntype SolanaSignatureStatusResponse = {\n slot: number;\n confirmations: number | null;\n err: TransactionError | null;\n confirmationStatus: 'processed' | 'confirmed' | 'finalized' | null;\n fee?: number;\n recentBlockhash?: string;\n instructions?: unknown[];\n};\n\n/**\n * @typedef SolanaFetcherParams\n * Parameters used for the Solana fetcher function.\n */\ntype SolanaFetcherParams = Parameters<PollingTrackerConfig<SolanaSignatureStatusResponse, Transaction>['fetcher']>[0];\n\n/**\n * Fetches and tracks Solana transactions using the `getSignatureStatuses` RPC method.\n * Transaction details (`getTransaction`) are only fetched once, if not already present in the transaction object.\n *\n * @param {SolanaFetcherParams} params - The fetcher parameters, automatically provided by the tracker.\n * @throws Will throw an error if the transaction adapter is not set to Solana.\n * @returns {Promise<void>} Resolves when the fetcher completes execution for the current polling cycle.\n */\nexport async function solanaFetcher({\n tx,\n stopPolling,\n onSuccess,\n onFailure,\n onIntervalTick,\n}: SolanaFetcherParams): Promise<void> {\n // Validate that the transaction uses the Solana adapter\n if (tx.adapter !== OrbitAdapter.SOLANA) {\n throw new Error('Tx adapter is not Solana. Please set the adapter to \"solana\" in the transaction object.');\n }\n\n try {\n // Initialize the Solana RPC client\n const rpc = createSolanaRPC({ rpcUrlOrMoniker: tx.rpcUrl ?? getCluster({ cluster: tx.chainId as string }) });\n\n // Fetch transaction signature status\n const statuses = await rpc.getSignatureStatuses([tx.txKey as Signature]).send();\n const status = statuses?.value?.[0];\n\n // Skip further processing if no status is found\n if (!status) {\n return;\n }\n\n // Extract or fetch transaction details only when missing\n let { fee, recentBlockhash, instructions } = tx;\n\n if (!fee || !recentBlockhash || !instructions) {\n const txDetails = await rpc\n .getTransaction(tx.txKey as Signature, { encoding: 'json', maxSupportedTransactionVersion: 0 })\n .send();\n const { meta, transaction } = txDetails || {};\n\n // If no transaction details are found, skip further processing\n if (!meta || !transaction) {\n return;\n }\n\n // Extract details from RPC response\n fee = Number(meta.fee ?? 0);\n recentBlockhash = transaction.message.recentBlockhash?.toString();\n instructions = transaction.message.instructions as unknown[];\n }\n\n // Construct the extended transaction status object\n const typedStatus: SolanaSignatureStatusResponse = {\n ...status,\n slot: Number(status.slot),\n confirmations: Number(status.confirmations ?? 0),\n fee,\n recentBlockhash,\n instructions,\n };\n\n // Trigger periodic updates for transaction tracking\n onIntervalTick?.(typedStatus);\n\n // Handle transaction error state\n if (typedStatus.err) {\n onFailure(typedStatus);\n stopPolling({ withoutRemoving: true });\n return;\n }\n\n // Handle finalized transaction state\n if (typedStatus.confirmationStatus === 'finalized') {\n onSuccess(typedStatus);\n stopPolling({ withoutRemoving: true });\n return;\n }\n\n // Stop polling if the transaction is unconfirmed for more than 1 hour\n const elapsedDays = dayjs().diff(dayjs.unix(tx.localTimestamp), 'hour');\n if (elapsedDays >= 1) {\n onFailure(typedStatus);\n stopPolling();\n }\n } catch (error) {\n console.error('Error in solanaFetcher:', error);\n onFailure({ err: error } as SolanaSignatureStatusResponse);\n stopPolling();\n }\n}\n\n/**\n * A higher-level tracker that integrates the Solana polling logic with the Pulsar store.\n *\n * @template T - The application-specific Solana transaction type.\n *\n * @param {object} params - Parameters to connect the Solana tracker with the store.\n * @param {T} params.tx - The Solana transaction being tracked.\n * @param {Function} params.updateTxParams - A callback to update specific fields of a transaction in the store.\n * @param {Function} [params.removeTxFromPool] - A function to remove a completed or canceled transaction from the store.\n * @returns {Promise<void>} Resolves when the tracker is successfully initialized.\n */\nexport async function solanaTrackerForStore<T extends Transaction>({\n tx,\n onSuccessCallback,\n ...rest\n}: Pick<ITxTrackingStore<T>, 'updateTxParams' | 'removeTxFromPool' | 'transactionsPool'> & {\n tx: T;\n} & OnSuccessCallback<T>): Promise<void> {\n return initializePollingTracker<SolanaSignatureStatusResponse, T>({\n tx,\n fetcher: solanaFetcher,\n removeTxFromPool: rest.removeTxFromPool,\n pollingInterval: 2500, // Polling interval: 2.5 seconds\n maxRetries: 10, // Max retries: 10 times\n\n /**\n * Success handler - updates the Pulsar store with finalized transaction details.\n *\n * @param {SolanaSignatureStatusResponse} response - The finalized transaction details.\n */\n onSuccess: (response) => {\n rest.updateTxParams(tx.txKey, {\n status: TransactionStatus.Success,\n pending: false,\n isError: false,\n finishedTimestamp: dayjs().unix(),\n fee: response.fee,\n instructions: response.instructions,\n recentBlockhash: response.recentBlockhash,\n confirmations: 'MAX',\n slot: response.slot,\n });\n\n // Trigger global success callbacks, if applicable\n const updatedTx = rest.transactionsPool[tx.txKey];\n if (onSuccessCallback && updatedTx) {\n onSuccessCallback(updatedTx);\n }\n },\n\n /**\n * Interval handler - updates interim transaction details in the store.\n *\n * @param {SolanaSignatureStatusResponse} response - The latest transaction status update.\n */\n onIntervalTick: (response) => {\n rest.updateTxParams(tx.txKey, {\n confirmations: response.confirmations ?? 0,\n slot: response.slot,\n fee: response.fee,\n instructions: response.instructions,\n recentBlockhash: response.recentBlockhash,\n });\n },\n\n /**\n * Failure handler - updates the store when the transaction fails or times out.\n *\n * @param {SolanaSignatureStatusResponse} response - The failure response details.\n */\n onFailure: (response) => {\n const errorMessage = response?.err\n ? `Transaction failed: ${JSON.stringify(response.err)}`\n : 'Transaction tracking timed out or the transaction was not found.';\n rest.updateTxParams(tx.txKey, {\n status: TransactionStatus.Failed,\n pending: false,\n isError: true,\n errorMessage,\n finishedTimestamp: dayjs().unix(),\n });\n },\n });\n}\n","/**\n * @file This file contains the primary router for initializing transaction trackers.\n */\n\nimport {\n ITxTrackingStore,\n OnSuccessCallback,\n Transaction,\n TransactionStatus,\n TransactionTracker,\n} from '@tuwaio/pulsar-core';\n\nimport { solanaTrackerForStore } from '../trackers/solanaTracker';\n\n/**\n * Initializes the correct background tracker for a given Solana transaction.\n * This function acts as a router, selecting the appropriate tracker based on the `tx.tracker` property.\n *\n * @template T - The transaction type.\n * @param {object} params - The parameters for initializing the tracker.\n * @param {T} params.tx - The transaction object to be tracked.\n * @param {TransactionTracker} params.tracker - The specific tracker to use.\n * @param {object} params.rest - The rest of the store's methods and state needed by the tracker.\n * @returns {Promise<void>} A promise that resolves when the tracker has been initialized.\n */\nexport async function checkAndInitializeTrackerInStore<T extends Transaction>({\n tx,\n tracker,\n ...rest\n}: {\n tx: T;\n tracker: TransactionTracker;\n} & OnSuccessCallback<T> &\n Pick<ITxTrackingStore<T>, 'updateTxParams' | 'removeTxFromPool' | 'transactionsPool'>): Promise<void> {\n switch (tracker) {\n case TransactionTracker.Solana:\n await solanaTrackerForStore({\n tx,\n ...rest,\n });\n break;\n default:\n console.error(`Unknown tracker type for Solana adapter: ${tracker}`);\n // If an unsupported tracker is specified, mark the transaction as failed.\n rest.updateTxParams(tx.txKey, {\n status: TransactionStatus.Failed,\n pending: false,\n isError: true,\n errorMessage: `Unsupported tracker type: \"${tracker}\"`,\n });\n break;\n }\n}\n","/**\n * @file This file contains a utility to verify the connected Solana chain.\n */\n\nimport { SolanaChainMismatchError } from '../errors';\n\n/**\n * Checks if the wallet's current chain matches the required chain for a transaction.\n * This function compares the `chain` property from the Wallet Standard account object\n * with the required chain identifier (e.g., 'solana:mainnet').\n *\n * @param {string} requiredChain - The chain identifier that the transaction requires.\n * @param {string} currentChain - The chain identifier the wallet is currently connected to.\n * @throws {SolanaChainMismatchError} If the connected chain does not match the required chain.\n */\nexport const checkSolanaChain = (requiredChain: string, currentChain: string): void => {\n if (currentChain !== requiredChain) {\n throw new SolanaChainMismatchError(requiredChain, currentChain);\n }\n};\n","/**\n * @file This file contains the factory function for creating the Solana adapter for Pulsar.\n */\n\nimport { getConnectorTypeFromName, lastConnectedConnectorHelpers, OrbitAdapter } from '@tuwaio/orbit-core';\nimport {\n createSolanaClientWithCache,\n getAvailableSolanaConnectors,\n getCluster,\n getConnectedSolanaConnector,\n getRpcUrlForCluster,\n getSolanaExplorerLink,\n} from '@tuwaio/orbit-solana';\nimport { Transaction, TransactionTracker, TxAdapter } from '@tuwaio/pulsar-core';\nimport { SolanaClusterMoniker } from 'gill';\n\nimport { SolanaChainMismatchError } from '../errors';\nimport { SolanaAdapterConfig } from '../types';\nimport { checkAndInitializeTrackerInStore } from '../utils/checkAndInitializeTrackerInStore';\nimport { checkSolanaChain } from '../utils/checkSolanaChain';\n\n/**\n * Creates a Solana adapter for the Pulsar transaction tracking engine.\n * This factory function produces a wallet-library-agnostic adapter that can be\n * configured for multiple Solana clusters (e.g., mainnet-beta, devnet) and\n * can operate even without a connected wallet for read-only tasks.\n *\n * @template T - The application-specific transaction type.\n * @param {SolanaAdapterConfig} config - The configuration object for the adapter.\n * @returns {TxAdapter<T>} The configured Solana transaction adapter.\n *\n * @throws {Error} Throws an error if the wagmi `config` is not provided.\n */\nexport function pulsarSolanaAdapter<T extends Transaction>(config: SolanaAdapterConfig): TxAdapter<T> {\n const { rpcUrls } = config;\n\n return {\n key: OrbitAdapter.SOLANA,\n\n getConnectorInfo: () => {\n const connectedConnector = getConnectedSolanaConnector();\n const localConnectedConnector = lastConnectedConnectorHelpers.getLastConnectedConnector();\n return {\n walletAddress: localConnectedConnector?.address ?? connectedConnector.accounts[0].address ?? '0x0',\n connectorType: getConnectorTypeFromName(OrbitAdapter.SOLANA, connectedConnector.name),\n };\n },\n\n checkChainForTx: async (txChain) => {\n const connectedConnector = getConnectedSolanaConnector();\n if (!connectedConnector) {\n throw new Error('Wallet not provided. Cannot perform chain check.');\n }\n try {\n checkSolanaChain(\n txChain as string,\n (lastConnectedConnectorHelpers.getLastConnectedConnector()?.chainId as string) ?? '',\n );\n } catch (e) {\n if (e instanceof SolanaChainMismatchError) throw e;\n throw new Error(`Chain check failed: ${e instanceof Error ? e.message : String(e)}`);\n }\n },\n\n checkTransactionsTracker: (actionTxKey) => ({\n tracker: TransactionTracker.Solana,\n txKey: actionTxKey as string,\n }),\n\n checkAndInitializeTrackerInStore: ({ tx, ...rest }) => {\n return checkAndInitializeTrackerInStore({\n tracker: tx.tracker,\n tx,\n ...rest,\n });\n },\n\n getExplorerUrl: (url, chainId) => {\n return getSolanaExplorerLink(url, chainId);\n },\n getExplorerTxUrl: (tx) => {\n return getSolanaExplorerLink(`/tx/${tx.txKey}`, tx.chainId);\n },\n\n retryTxAction: async ({ onClose, txKey, executeTxAction, tx }) => {\n onClose(txKey);\n\n const connectors = getAvailableSolanaConnectors();\n const connectedConnector = connectors.filter((connector) => connector.accounts.length > 0)[0];\n\n if (!connectedConnector || !connectedConnector.accounts[0].address || connectedConnector.accounts[0].address === '0x0') {\n throw new Error('Retry failed: A wallet must be connected.');\n }\n if (!executeTxAction) {\n throw new Error('Retry failed: executeTxAction function is not provided.');\n }\n\n const clusterForRetry = getCluster({ cluster: tx?.desiredChainID as string }) as SolanaClusterMoniker;\n const rpcUrlForRetry = tx.rpcUrl ?? getRpcUrlForCluster({ cluster: clusterForRetry, rpcUrls });\n\n if (!rpcUrlForRetry) {\n throw new Error('Retry failed: Could not determine RPC endpoint for the transaction chain.');\n }\n\n const client = createSolanaClientWithCache({ rpcUrlOrMoniker: rpcUrlForRetry, rpcUrls });\n\n await executeTxAction({\n actionFunction: () =>\n tx.actionFunction({\n client,\n ...tx.payload,\n }),\n params: tx,\n defaultTracker: TransactionTracker.Solana,\n });\n },\n };\n}\n","/**\n * @file This file contains a utility function for signing and sending Solana transactions.\n * It simplifies the process of creating, signing, and broadcasting a transaction to the network.\n */\n\nimport type { Instruction, SolanaClient, TransactionSendingSigner } from 'gill';\nimport { createTransaction, getBase58Decoder, signAndSendTransactionMessageWithSigners } from 'gill';\n\n/**\n * Creates, signs, and sends a Solana transaction with one or more instructions.\n *\n * This async function orchestrates the common flow for broadcasting a transaction:\n * 1. Fetches the latest blockhash from the RPC.\n * 2. Creates a versioned transaction (`v0`).\n * 3. Signs the transaction with the provided signer.\n * 4. Sends the transaction to the network.\n * 5. Decodes and returns the resulting transaction signature.\n *\n * @param {object} params - The parameters for signing and sending the transaction.\n * @param {SolanaClient} params.client - The Solana client instance for RPC communication.\n * @param {TransactionSendingSigner} params.signer - The signer (e.g., a wallet) responsible for signing the transaction.\n * @param {Instruction | Instruction[]} params.instruction - A single instruction or an array of instructions to include in the transaction.\n * @returns A promise that resolves to the transaction signature.\n * @throws Will throw an error if any of the async operations (fetching blockhash, signing, sending) fail.\n *\n * @example\n * const signature = await signAndSendSolanaTx({\n * client: mySolanaClient,\n * signer: wallet,\n * instruction: myTransferInstruction,\n * });\n * console.log('Transaction sent with signature:', signature);\n */\nexport async function signAndSendSolanaTx({\n client,\n signer,\n instruction,\n}: {\n client: SolanaClient;\n signer: TransactionSendingSigner;\n instruction: Instruction | Instruction[];\n}) {\n // 1. Fetch the latest blockhash to ensure transaction validity.\n const { value: latestBlockhash } = await client.rpc.getLatestBlockhash().send();\n\n // 2. Create a version 0 transaction, which is the current standard.\n const transaction = createTransaction({\n feePayer: signer,\n version: 0,\n latestBlockhash,\n instructions: Array.isArray(instruction) ? instruction : [instruction],\n });\n\n // 3. Sign the transaction message and send it to the network.\n const signature = await signAndSendTransactionMessageWithSigners(transaction);\n\n // 4. Decode the resulting signature into the final format.\n return getBase58Decoder().decode(signature);\n}\n"]}