@dynamic-labs-sdk/solana 0.13.0 → 0.15.0

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.
Files changed (137) hide show
  1. package/dist/{addSolanaWalletStandardExtension-D5uAzwwi.cjs.js → addSolanaWalletStandardExtension-Bf8r6-4V.cjs.js} +6 -4
  2. package/dist/addSolanaWalletStandardExtension-Bf8r6-4V.cjs.js.map +1 -0
  3. package/dist/{addSolanaWalletStandardExtension-DikNvaRF.esm.js → addSolanaWalletStandardExtension-BngOUdym.esm.js} +4 -2
  4. package/dist/addSolanaWalletStandardExtension-BngOUdym.esm.js.map +1 -0
  5. package/dist/{addWaasSolanaExtension-FUlrXwXm.esm.js → addWaasSolanaExtension-BYxLx6fj.esm.js} +6 -29
  6. package/dist/addWaasSolanaExtension-BYxLx6fj.esm.js.map +1 -0
  7. package/dist/{addWaasSolanaExtension-DBfiocjd.cjs.js → addWaasSolanaExtension-CSzXRhvr.cjs.js} +10 -39
  8. package/dist/addWaasSolanaExtension-CSzXRhvr.cjs.js.map +1 -0
  9. package/dist/checkoutTransaction.types.d.ts +6 -0
  10. package/dist/checkoutTransaction.types.d.ts.map +1 -0
  11. package/dist/exports/index.d.ts +8 -3
  12. package/dist/exports/index.d.ts.map +1 -1
  13. package/dist/index.cjs.js +1005 -46
  14. package/dist/index.cjs.js.map +1 -1
  15. package/dist/index.esm.js +989 -36
  16. package/dist/index.esm.js.map +1 -1
  17. package/dist/isSolanaGasSponsorshipEnabled/index.d.ts +2 -0
  18. package/dist/isSolanaGasSponsorshipEnabled/index.d.ts.map +1 -0
  19. package/dist/isSolanaGasSponsorshipEnabled/isSolanaGasSponsorshipEnabled.d.ts +8 -0
  20. package/dist/isSolanaGasSponsorshipEnabled/isSolanaGasSponsorshipEnabled.d.ts.map +1 -0
  21. package/dist/phantomRedirect/PhantomRedirectWalletProvider.types.d.ts +112 -0
  22. package/dist/phantomRedirect/PhantomRedirectWalletProvider.types.d.ts.map +1 -0
  23. package/dist/phantomRedirect/addPhantomRedirectSolanaExtension/addPhantomRedirectSolanaExtension.d.ts +115 -0
  24. package/dist/phantomRedirect/addPhantomRedirectSolanaExtension/addPhantomRedirectSolanaExtension.d.ts.map +1 -0
  25. package/dist/phantomRedirect/addPhantomRedirectSolanaExtension/index.d.ts +3 -0
  26. package/dist/phantomRedirect/addPhantomRedirectSolanaExtension/index.d.ts.map +1 -0
  27. package/dist/phantomRedirect/completePhantomRedirect/completePhantomRedirect.d.ts +32 -0
  28. package/dist/phantomRedirect/completePhantomRedirect/completePhantomRedirect.d.ts.map +1 -0
  29. package/dist/phantomRedirect/completePhantomRedirect/index.d.ts +3 -0
  30. package/dist/phantomRedirect/completePhantomRedirect/index.d.ts.map +1 -0
  31. package/dist/phantomRedirect/createPhantomRedirectWalletProvider/createPhantomRedirectWalletProvider.d.ts +17 -0
  32. package/dist/phantomRedirect/createPhantomRedirectWalletProvider/createPhantomRedirectWalletProvider.d.ts.map +1 -0
  33. package/dist/phantomRedirect/createPhantomRedirectWalletProvider/index.d.ts +3 -0
  34. package/dist/phantomRedirect/createPhantomRedirectWalletProvider/index.d.ts.map +1 -0
  35. package/dist/phantomRedirect/detectPhantomRedirect/detectPhantomRedirect.d.ts +17 -0
  36. package/dist/phantomRedirect/detectPhantomRedirect/detectPhantomRedirect.d.ts.map +1 -0
  37. package/dist/phantomRedirect/detectPhantomRedirect/index.d.ts +3 -0
  38. package/dist/phantomRedirect/detectPhantomRedirect/index.d.ts.map +1 -0
  39. package/dist/phantomRedirect/errors/NoPendingPhantomRequestError.d.ts +5 -0
  40. package/dist/phantomRedirect/errors/NoPendingPhantomRequestError.d.ts.map +1 -0
  41. package/dist/phantomRedirect/errors/NoPhantomSessionError.d.ts +5 -0
  42. package/dist/phantomRedirect/errors/NoPhantomSessionError.d.ts.map +1 -0
  43. package/dist/phantomRedirect/errors/PhantomMissingEncryptionParamsError.d.ts +5 -0
  44. package/dist/phantomRedirect/errors/PhantomMissingEncryptionParamsError.d.ts.map +1 -0
  45. package/dist/phantomRedirect/errors/PhantomRedirectDecryptionError.d.ts +5 -0
  46. package/dist/phantomRedirect/errors/PhantomRedirectDecryptionError.d.ts.map +1 -0
  47. package/dist/phantomRedirect/errors/PhantomRedirectRejectedError.d.ts +9 -0
  48. package/dist/phantomRedirect/errors/PhantomRedirectRejectedError.d.ts.map +1 -0
  49. package/dist/phantomRedirect/errors/PhantomRedirectTimeoutError.d.ts +5 -0
  50. package/dist/phantomRedirect/errors/PhantomRedirectTimeoutError.d.ts.map +1 -0
  51. package/dist/phantomRedirect/phantomRedirect.broadcast.types.d.ts +6 -0
  52. package/dist/phantomRedirect/phantomRedirect.broadcast.types.d.ts.map +1 -0
  53. package/dist/phantomRedirect/phantomRedirect.constants.d.ts +5 -0
  54. package/dist/phantomRedirect/phantomRedirect.constants.d.ts.map +1 -0
  55. package/dist/phantomRedirect/phantomRedirect.events.d.ts +152 -0
  56. package/dist/phantomRedirect/phantomRedirect.events.d.ts.map +1 -0
  57. package/dist/phantomRedirect/storage/pendingRequestStorageSchema/index.d.ts +2 -0
  58. package/dist/phantomRedirect/storage/pendingRequestStorageSchema/index.d.ts.map +1 -0
  59. package/dist/phantomRedirect/storage/pendingRequestStorageSchema/pendingRequestStorageSchema.d.ts +15 -0
  60. package/dist/phantomRedirect/storage/pendingRequestStorageSchema/pendingRequestStorageSchema.d.ts.map +1 -0
  61. package/dist/phantomRedirect/storage/phantomSessionStorageSchema/index.d.ts +2 -0
  62. package/dist/phantomRedirect/storage/phantomSessionStorageSchema/index.d.ts.map +1 -0
  63. package/dist/phantomRedirect/storage/phantomSessionStorageSchema/phantomSessionStorageSchema.d.ts +14 -0
  64. package/dist/phantomRedirect/storage/phantomSessionStorageSchema/phantomSessionStorageSchema.d.ts.map +1 -0
  65. package/dist/phantomRedirect/utils/broadcastPhantomEvent/broadcastPhantomEvent.d.ts +16 -0
  66. package/dist/phantomRedirect/utils/broadcastPhantomEvent/broadcastPhantomEvent.d.ts.map +1 -0
  67. package/dist/phantomRedirect/utils/broadcastPhantomEvent/index.d.ts +2 -0
  68. package/dist/phantomRedirect/utils/broadcastPhantomEvent/index.d.ts.map +1 -0
  69. package/dist/phantomRedirect/utils/buildPhantomDeepLink/buildPhantomDeepLink.d.ts +23 -0
  70. package/dist/phantomRedirect/utils/buildPhantomDeepLink/buildPhantomDeepLink.d.ts.map +1 -0
  71. package/dist/phantomRedirect/utils/buildPhantomDeepLink/index.d.ts +3 -0
  72. package/dist/phantomRedirect/utils/buildPhantomDeepLink/index.d.ts.map +1 -0
  73. package/dist/phantomRedirect/utils/cleanPhantomParamsFromUrl/cleanPhantomParamsFromUrl.d.ts +15 -0
  74. package/dist/phantomRedirect/utils/cleanPhantomParamsFromUrl/cleanPhantomParamsFromUrl.d.ts.map +1 -0
  75. package/dist/phantomRedirect/utils/cleanPhantomParamsFromUrl/index.d.ts +3 -0
  76. package/dist/phantomRedirect/utils/cleanPhantomParamsFromUrl/index.d.ts.map +1 -0
  77. package/dist/phantomRedirect/utils/crypto/createNaClSharedSecret/createNaClSharedSecret.d.ts +13 -0
  78. package/dist/phantomRedirect/utils/crypto/createNaClSharedSecret/createNaClSharedSecret.d.ts.map +1 -0
  79. package/dist/phantomRedirect/utils/crypto/createNaClSharedSecret/index.d.ts +3 -0
  80. package/dist/phantomRedirect/utils/crypto/createNaClSharedSecret/index.d.ts.map +1 -0
  81. package/dist/phantomRedirect/utils/crypto/decryptPayload/decryptPayload.d.ts +16 -0
  82. package/dist/phantomRedirect/utils/crypto/decryptPayload/decryptPayload.d.ts.map +1 -0
  83. package/dist/phantomRedirect/utils/crypto/decryptPayload/index.d.ts +3 -0
  84. package/dist/phantomRedirect/utils/crypto/decryptPayload/index.d.ts.map +1 -0
  85. package/dist/phantomRedirect/utils/crypto/encryptPayload/encryptPayload.d.ts +17 -0
  86. package/dist/phantomRedirect/utils/crypto/encryptPayload/encryptPayload.d.ts.map +1 -0
  87. package/dist/phantomRedirect/utils/crypto/encryptPayload/index.d.ts +3 -0
  88. package/dist/phantomRedirect/utils/crypto/encryptPayload/index.d.ts.map +1 -0
  89. package/dist/phantomRedirect/utils/crypto/generateNaClKeyPair/generateNaClKeyPair.d.ts +11 -0
  90. package/dist/phantomRedirect/utils/crypto/generateNaClKeyPair/generateNaClKeyPair.d.ts.map +1 -0
  91. package/dist/phantomRedirect/utils/crypto/generateNaClKeyPair/index.d.ts +3 -0
  92. package/dist/phantomRedirect/utils/crypto/generateNaClKeyPair/index.d.ts.map +1 -0
  93. package/dist/phantomRedirect/utils/getPhantomCluster/getPhantomCluster.d.ts +23 -0
  94. package/dist/phantomRedirect/utils/getPhantomCluster/getPhantomCluster.d.ts.map +1 -0
  95. package/dist/phantomRedirect/utils/getPhantomOriginTab/getPhantomOriginTab.d.ts +19 -0
  96. package/dist/phantomRedirect/utils/getPhantomOriginTab/getPhantomOriginTab.d.ts.map +1 -0
  97. package/dist/phantomRedirect/utils/getPhantomOriginTab/index.d.ts +3 -0
  98. package/dist/phantomRedirect/utils/getPhantomOriginTab/index.d.ts.map +1 -0
  99. package/dist/phantomRedirect/utils/listenForPhantomBroadcast/index.d.ts +2 -0
  100. package/dist/phantomRedirect/utils/listenForPhantomBroadcast/index.d.ts.map +1 -0
  101. package/dist/phantomRedirect/utils/listenForPhantomBroadcast/listenForPhantomBroadcast.d.ts +15 -0
  102. package/dist/phantomRedirect/utils/listenForPhantomBroadcast/listenForPhantomBroadcast.d.ts.map +1 -0
  103. package/dist/phantomRedirect/utils/parsePhantomRedirectParams/index.d.ts +3 -0
  104. package/dist/phantomRedirect/utils/parsePhantomRedirectParams/index.d.ts.map +1 -0
  105. package/dist/phantomRedirect/utils/parsePhantomRedirectParams/parsePhantomRedirectParams.d.ts +22 -0
  106. package/dist/phantomRedirect/utils/parsePhantomRedirectParams/parsePhantomRedirectParams.d.ts.map +1 -0
  107. package/dist/solanaTransferAmount-C1cnaJBQ.esm.js +221 -0
  108. package/dist/solanaTransferAmount-C1cnaJBQ.esm.js.map +1 -0
  109. package/dist/solanaTransferAmount-sL92hrfS.cjs.js +287 -0
  110. package/dist/solanaTransferAmount-sL92hrfS.cjs.js.map +1 -0
  111. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  112. package/dist/utils/solanaExecuteCheckoutTransaction/index.d.ts +2 -0
  113. package/dist/utils/solanaExecuteCheckoutTransaction/index.d.ts.map +1 -0
  114. package/dist/utils/solanaExecuteCheckoutTransaction/solanaExecuteCheckoutTransaction.d.ts +19 -0
  115. package/dist/utils/solanaExecuteCheckoutTransaction/solanaExecuteCheckoutTransaction.d.ts.map +1 -0
  116. package/dist/utils/solanaTransferAmount/index.d.ts +2 -0
  117. package/dist/utils/solanaTransferAmount/index.d.ts.map +1 -0
  118. package/dist/utils/solanaTransferAmount/solanaTransferAmount.d.ts +14 -0
  119. package/dist/utils/solanaTransferAmount/solanaTransferAmount.d.ts.map +1 -0
  120. package/dist/waas/utils/createWalletProviderForWaasSolana/createWalletProviderForWaasSolana.d.ts.map +1 -1
  121. package/dist/waas.cjs.js +4 -4
  122. package/dist/waas.cjs.js.map +1 -1
  123. package/dist/waas.esm.js +2 -2
  124. package/dist/walletConnect/createWalletProviderFromWalletConnectSolanaSession/createWalletProviderFromWalletConnectSolanaSession.d.ts.map +1 -1
  125. package/dist/walletStandard/utils/createWalletProviderFromSolanaStandardWallet/createWalletProviderFromSolanaStandardWallet.d.ts.map +1 -1
  126. package/dist/walletStandard.cjs.js +3 -3
  127. package/dist/walletStandard.cjs.js.map +1 -1
  128. package/dist/walletStandard.esm.js +2 -2
  129. package/package.json +8 -5
  130. package/dist/addSolanaWalletStandardExtension-D5uAzwwi.cjs.js.map +0 -1
  131. package/dist/addSolanaWalletStandardExtension-DikNvaRF.esm.js.map +0 -1
  132. package/dist/addWaasSolanaExtension-DBfiocjd.cjs.js.map +0 -1
  133. package/dist/addWaasSolanaExtension-FUlrXwXm.esm.js.map +0 -1
  134. package/dist/isVersionedTransaction-CSkcEh-G.cjs.js +0 -72
  135. package/dist/isVersionedTransaction-CSkcEh-G.cjs.js.map +0 -1
  136. package/dist/isVersionedTransaction-s73AwAKu.esm.js +0 -48
  137. package/dist/isVersionedTransaction-s73AwAKu.esm.js.map +0 -1
package/dist/index.cjs.js CHANGED
@@ -1,12 +1,17 @@
1
- const require_addSolanaWalletStandardExtension = require('./addSolanaWalletStandardExtension-D5uAzwwi.cjs.js');
2
- const require_isVersionedTransaction = require('./isVersionedTransaction-CSkcEh-G.cjs.js');
3
- const require_addWaasSolanaExtension = require('./addWaasSolanaExtension-DBfiocjd.cjs.js');
1
+ const require_addSolanaWalletStandardExtension = require('./addSolanaWalletStandardExtension-Bf8r6-4V.cjs.js');
2
+ const require_solanaTransferAmount = require('./solanaTransferAmount-sL92hrfS.cjs.js');
3
+ const require_addWaasSolanaExtension = require('./addWaasSolanaExtension-CSzXRhvr.cjs.js');
4
4
  let _dynamic_labs_sdk_assert_package_version = require("@dynamic-labs-sdk/assert-package-version");
5
5
  let _dynamic_labs_sdk_client_core = require("@dynamic-labs-sdk/client/core");
6
6
  let _solana_web3_js = require("@solana/web3.js");
7
7
  let _dynamic_labs_sdk_client = require("@dynamic-labs-sdk/client");
8
+ let _dynamic_labs_sdk_api_core = require("@dynamic-labs/sdk-api-core");
8
9
  let bs58 = require("bs58");
9
10
  bs58 = require_addSolanaWalletStandardExtension.__toESM(bs58);
11
+ let zod_mini = require("zod/mini");
12
+ zod_mini = require_addSolanaWalletStandardExtension.__toESM(zod_mini);
13
+ let tweetnacl = require("tweetnacl");
14
+ tweetnacl = require_addSolanaWalletStandardExtension.__toESM(tweetnacl);
10
15
 
11
16
  //#region src/addSolanaExtension/addSolanaExtension.ts
12
17
  /**
@@ -23,22 +28,6 @@ const addSolanaExtension = (client = (0, _dynamic_labs_sdk_client_core.getDefaul
23
28
  require_addWaasSolanaExtension.addWaasSolanaExtension(client);
24
29
  };
25
30
 
26
- //#endregion
27
- //#region src/errors/NotSolanaProviderError/NotSolanaProviderError.ts
28
- var NotSolanaProviderError = class extends _dynamic_labs_sdk_client.BaseError {
29
- providerKey;
30
- constructor(params) {
31
- super({
32
- cause: null,
33
- code: "not_solana_provider_error",
34
- docsUrl: null,
35
- name: "NotSolanaProviderError",
36
- shortMessage: "Provider is not a Solana wallet provider"
37
- });
38
- this.providerKey = params.providerKey;
39
- }
40
- };
41
-
42
31
  //#endregion
43
32
  //#region src/isSolanaNetworkProvider/isSolanaNetworkProvider.ts
44
33
  /**
@@ -49,16 +38,6 @@ var NotSolanaProviderError = class extends _dynamic_labs_sdk_client.BaseError {
49
38
  */
50
39
  const isSolanaNetworkProvider = (networkProvider) => networkProvider.chain === "SOL";
51
40
 
52
- //#endregion
53
- //#region src/isSolanaWalletAccount/isSolanaWalletAccount.ts
54
- /**
55
- * Type guard function to check if a wallet account is a Solana wallet account.
56
- *
57
- * @param walletAccount - The wallet account to check.
58
- * @returns True if the wallet account is a Solana wallet account, false otherwise.
59
- */
60
- const isSolanaWalletAccount = (walletAccount) => walletAccount.chain === "SOL";
61
-
62
41
  //#endregion
63
42
  //#region src/utils/calculateSolanaTransactionFee/calculateSolanaTransactionFee.ts
64
43
  const MAX_RETRIES = 5;
@@ -82,7 +61,7 @@ const sleep = (ms) => new Promise((resolve) => {
82
61
  const calculateSolanaTransactionFee = async ({ transaction, networkData, nativeTokenPriceUsd }) => {
83
62
  try {
84
63
  const connection = new _solana_web3_js.Connection(networkData.rpcUrls.http[0]);
85
- if (require_isVersionedTransaction.isVersionedTransaction(transaction)) {
64
+ if (require_solanaTransferAmount.isVersionedTransaction(transaction)) {
86
65
  if (!transaction.message.recentBlockhash) {
87
66
  const { blockhash } = await connection.getLatestBlockhash();
88
67
  transaction.message.recentBlockhash = blockhash;
@@ -91,7 +70,7 @@ const calculateSolanaTransactionFee = async ({ transaction, networkData, nativeT
91
70
  const { blockhash } = await connection.getLatestBlockhash();
92
71
  transaction.recentBlockhash = blockhash;
93
72
  }
94
- const message = require_isVersionedTransaction.isVersionedTransaction(transaction) ? transaction.message : transaction.compileMessage();
73
+ const message = require_solanaTransferAmount.isVersionedTransaction(transaction) ? transaction.message : transaction.compileMessage();
95
74
  let lastError;
96
75
  for (let attempt = 0; attempt < MAX_RETRIES; attempt++) try {
97
76
  const feeResponse = await connection.getFeeForMessage(message);
@@ -157,18 +136,18 @@ const calculateSolanaTransactionFee = async ({ transaction, networkData, nativeT
157
136
  * @throws {FeeEstimationFailedError} If includeFees is true and fee calculation fails.
158
137
  */
159
138
  const simulateSolanaTransaction = async ({ walletAccount, transaction, includeFees = false }, client = (0, _dynamic_labs_sdk_client.getDefaultClient)()) => {
160
- if (!isSolanaWalletAccount(walletAccount)) throw new _dynamic_labs_sdk_client.InvalidParamError("Wallet account must be a Solana wallet account");
139
+ if (!require_solanaTransferAmount.isSolanaWalletAccount(walletAccount)) throw new _dynamic_labs_sdk_client.InvalidParamError("Wallet account must be a Solana wallet account");
161
140
  const { networkData } = await (0, _dynamic_labs_sdk_client.getActiveNetworkData)({ walletAccount }, client);
162
141
  if (!networkData) throw new _dynamic_labs_sdk_client.InvalidParamError("Network data not found for wallet account");
163
142
  try {
164
- const transactionBytes = require_isVersionedTransaction.isVersionedTransaction(transaction) ? transaction.serialize() : transaction.serialize({
143
+ const transactionBytes = require_solanaTransferAmount.isVersionedTransaction(transaction) ? transaction.serialize() : transaction.serialize({
165
144
  requireAllSignatures: false,
166
145
  verifySignatures: false
167
146
  });
168
147
  const serialized = bs58.default.encode(transactionBytes);
169
148
  console.log("[SIMULATE SOLANA TX] Serialization details:", {
170
149
  accountAddress: walletAccount.address,
171
- isVersioned: require_isVersionedTransaction.isVersionedTransaction(transaction),
150
+ isVersioned: require_solanaTransferAmount.isVersionedTransaction(transaction),
172
151
  serializedBase58: serialized,
173
152
  serializedLength: serialized.length,
174
153
  transactionLength: transactionBytes.length
@@ -189,7 +168,7 @@ const simulateSolanaTransaction = async ({ walletAccount, transaction, includeFe
189
168
  let feeData;
190
169
  if (includeFees) {
191
170
  const walletPublicKey = new _solana_web3_js.PublicKey(walletAccount.address);
192
- const feePayer = require_isVersionedTransaction.isVersionedTransaction(transaction) ? transaction.message.staticAccountKeys[0] : transaction.feePayer;
171
+ const feePayer = require_solanaTransferAmount.isVersionedTransaction(transaction) ? transaction.message.staticAccountKeys[0] : transaction.feePayer;
193
172
  if (feePayer && !feePayer.equals(walletPublicKey)) feeData = {
194
173
  humanReadableAmount: "0",
195
174
  nativeAmount: 0n,
@@ -224,9 +203,985 @@ const simulateSolanaTransaction = async ({ walletAccount, transaction, includeFe
224
203
  };
225
204
 
226
205
  //#endregion
227
- //#region src/isSolanaWalletProvider/isSolanaWalletProvider.ts
228
- const isSolanaWalletProvider = (provider) => {
229
- return provider.chain === "SOL";
206
+ //#region src/phantomRedirect/errors/NoPendingPhantomRequestError.ts
207
+ var NoPendingPhantomRequestError = class extends _dynamic_labs_sdk_client.BaseError {
208
+ constructor() {
209
+ super({
210
+ cause: null,
211
+ code: "no_pending_phantom_request_error",
212
+ docsUrl: null,
213
+ name: "NoPendingPhantomRequestError",
214
+ shortMessage: "No pending Phantom request found. The request may have already been processed or expired."
215
+ });
216
+ }
217
+ };
218
+
219
+ //#endregion
220
+ //#region src/phantomRedirect/errors/NoPhantomSessionError.ts
221
+ var NoPhantomSessionError = class extends _dynamic_labs_sdk_client.BaseError {
222
+ constructor() {
223
+ super({
224
+ cause: null,
225
+ code: "no_phantom_session_error",
226
+ docsUrl: null,
227
+ name: "NoPhantomSessionError",
228
+ shortMessage: "No Phantom session found. Please connect first."
229
+ });
230
+ }
231
+ };
232
+
233
+ //#endregion
234
+ //#region src/phantomRedirect/errors/PhantomMissingEncryptionParamsError.ts
235
+ var PhantomMissingEncryptionParamsError = class extends _dynamic_labs_sdk_client.BaseError {
236
+ constructor() {
237
+ super({
238
+ cause: null,
239
+ code: "phantom_missing_encryption_params_error",
240
+ docsUrl: null,
241
+ name: "PhantomMissingEncryptionParamsError",
242
+ shortMessage: "Phantom redirect response is missing required encryption parameters (phantomPublicKey, data, or nonce)."
243
+ });
244
+ }
245
+ };
246
+
247
+ //#endregion
248
+ //#region src/phantomRedirect/errors/PhantomRedirectRejectedError.ts
249
+ var PhantomRedirectRejectedError = class extends _dynamic_labs_sdk_client.BaseError {
250
+ constructor({ errorCode, errorMessage }) {
251
+ super({
252
+ cause: null,
253
+ code: "phantom_redirect_rejected_error",
254
+ details: errorMessage,
255
+ docsUrl: null,
256
+ metaMessages: [`Error Code: ${errorCode}`],
257
+ name: "PhantomRedirectRejectedError",
258
+ shortMessage: "User rejected the request in Phantom wallet."
259
+ });
260
+ }
261
+ };
262
+
263
+ //#endregion
264
+ //#region src/phantomRedirect/phantomRedirect.constants.ts
265
+ const PHANTOM_DEEPLINK_BASE_URL = "https://phantom.app/ul/v1";
266
+ const PHANTOM_SESSION_STORAGE_KEY = "phantom_session";
267
+ const PHANTOM_PENDING_REQUEST_STORAGE_KEY = "phantom_pending_request";
268
+
269
+ //#endregion
270
+ //#region src/phantomRedirect/storage/pendingRequestStorageSchema/pendingRequestStorageSchema.ts
271
+ /**
272
+ * Storage schema for tracking pending Phantom wallet requests.
273
+ * This temporary data is used to match redirect responses with their
274
+ * originating requests and includes the encryption keys needed for decryption.
275
+ */
276
+ const pendingRequestStorageKeySchema = (0, _dynamic_labs_sdk_client_core.createStorageKeySchema)({
277
+ key: PHANTOM_PENDING_REQUEST_STORAGE_KEY,
278
+ schema: zod_mini.object({
279
+ dappPublicKey: zod_mini.string(),
280
+ dappSecretKey: zod_mini.string(),
281
+ message: zod_mini.optional(zod_mini.string()),
282
+ method: zod_mini.string(),
283
+ requestId: zod_mini.string(),
284
+ timestamp: zod_mini.number(),
285
+ walletAddress: zod_mini.optional(zod_mini.string())
286
+ })
287
+ });
288
+
289
+ //#endregion
290
+ //#region src/phantomRedirect/storage/phantomSessionStorageSchema/phantomSessionStorageSchema.ts
291
+ /**
292
+ * Storage schema for persisting Phantom wallet session data.
293
+ * This includes the encryption keys and session information needed
294
+ * for subsequent operations after the initial connection.
295
+ */
296
+ const phantomSessionStorageKeySchema = (0, _dynamic_labs_sdk_client_core.createStorageKeySchema)({
297
+ key: PHANTOM_SESSION_STORAGE_KEY,
298
+ schema: zod_mini.object({
299
+ dappPublicKey: zod_mini.string(),
300
+ dappSecretKey: zod_mini.string(),
301
+ phantomPublicKey: zod_mini.string(),
302
+ sessionToken: zod_mini.string(),
303
+ sharedSecret: zod_mini.string(),
304
+ walletAddress: zod_mini.string()
305
+ })
306
+ });
307
+
308
+ //#endregion
309
+ //#region src/phantomRedirect/utils/broadcastPhantomEvent/broadcastPhantomEvent.ts
310
+ /**
311
+ * Broadcasts a Phantom redirect event to other tabs via the crossTabBroadcast
312
+ * service.
313
+ *
314
+ * Used by the redirect-completion tab to notify the originating tab that
315
+ * an operation has finished, since onceEvent listeners are in-memory and
316
+ * do not cross tab boundaries.
317
+ *
318
+ * @param params.event - The DynamicEvents event name to broadcast
319
+ * @param params.args - The event arguments to include in the message
320
+ * @param client - The Dynamic client instance
321
+ */
322
+ const broadcastPhantomEvent = ({ args, event }, client) => {
323
+ (0, _dynamic_labs_sdk_client_core.getCore)(client).crossTabBroadcast.send({
324
+ args,
325
+ event
326
+ });
327
+ };
328
+
329
+ //#endregion
330
+ //#region src/phantomRedirect/utils/crypto/createNaClSharedSecret/createNaClSharedSecret.ts
331
+ /**
332
+ * Creates a shared secret for NaCl box encryption using our secret key and their public key.
333
+ *
334
+ * @param params.ourSecretKey - Our base58-encoded secret key
335
+ * @param params.theirPublicKey - Their base58-encoded public key
336
+ * @returns The base58-encoded shared secret
337
+ */
338
+ const createNaClSharedSecret = ({ ourSecretKey, theirPublicKey }) => {
339
+ const sharedSecret = tweetnacl.default.box.before(bs58.default.decode(theirPublicKey), bs58.default.decode(ourSecretKey));
340
+ return bs58.default.encode(sharedSecret);
341
+ };
342
+
343
+ //#endregion
344
+ //#region src/phantomRedirect/errors/PhantomRedirectDecryptionError.ts
345
+ var PhantomRedirectDecryptionError = class extends _dynamic_labs_sdk_client.BaseError {
346
+ constructor() {
347
+ super({
348
+ cause: null,
349
+ code: "phantom_redirect_decryption_error",
350
+ docsUrl: null,
351
+ name: "PhantomRedirectDecryptionError",
352
+ shortMessage: "Failed to decrypt Phantom redirect response. The encryption keys may be invalid."
353
+ });
354
+ }
355
+ };
356
+
357
+ //#endregion
358
+ //#region src/phantomRedirect/utils/crypto/decryptPayload/decryptPayload.ts
359
+ /**
360
+ * Decrypts a payload using NaCl box encryption with a shared secret.
361
+ *
362
+ * @param params.data - The base58-encoded encrypted data
363
+ * @param params.nonce - The base58-encoded nonce
364
+ * @param params.sharedSecret - The base58-encoded shared secret
365
+ * @returns The decrypted payload object
366
+ * @throws {PhantomRedirectDecryptionError} If decryption fails
367
+ */
368
+ const decryptPayload = ({ data, nonce, sharedSecret }) => {
369
+ let decrypted;
370
+ try {
371
+ decrypted = tweetnacl.default.box.open.after(bs58.default.decode(data), bs58.default.decode(nonce), bs58.default.decode(sharedSecret));
372
+ } catch {
373
+ throw new PhantomRedirectDecryptionError();
374
+ }
375
+ if (!decrypted) throw new PhantomRedirectDecryptionError();
376
+ const decryptedString = (0, _dynamic_labs_sdk_client_core.getBuffer)().from(decrypted).toString("utf-8");
377
+ try {
378
+ return JSON.parse(decryptedString);
379
+ } catch {
380
+ throw new PhantomRedirectDecryptionError();
381
+ }
382
+ };
383
+
384
+ //#endregion
385
+ //#region src/phantomRedirect/utils/getPhantomOriginTab/getPhantomOriginTab.ts
386
+ /**
387
+ * Per-client service that tracks whether this JavaScript context is the
388
+ * **originating tab** that initiated a Phantom redirect request.
389
+ *
390
+ * Calling `getPhantomOriginTab(client)` for the first time lazily creates the
391
+ * service with `isOriginTab: false`. `setupPhantomListeners` sets it to `true`
392
+ * immediately when a request is initiated, so `completePhantomRedirect` can
393
+ * detect clone tabs by checking this flag.
394
+ *
395
+ * Because the service is stored in the client's `runtimeServices` Map (one
396
+ * entry per client instance), it is naturally scoped to the current JavaScript
397
+ * context — no browser globals (`sessionStorage`, `window`) are needed, making
398
+ * this approach compatible with SSR and React Native.
399
+ */
400
+ const getPhantomOriginTab = (0, _dynamic_labs_sdk_client_core.createRuntimeServiceAccessKey)("phantomOriginTab", () => ({ isOriginTab: false }));
401
+
402
+ //#endregion
403
+ //#region src/phantomRedirect/utils/parsePhantomRedirectParams/parsePhantomRedirectParams.ts
404
+ /**
405
+ * Parses Phantom wallet redirect parameters from a URL.
406
+ *
407
+ * Extracts both success and error parameters from the redirect URL,
408
+ * including encrypted response data or error information.
409
+ *
410
+ * @param params.url - The redirect URL containing Phantom parameters
411
+ * @returns Object containing the parsed redirect parameters
412
+ */
413
+ const parsePhantomRedirectParams = ({ url }) => {
414
+ const searchParams = url.searchParams;
415
+ return {
416
+ data: searchParams.get("data") ?? void 0,
417
+ errorCode: searchParams.get("errorCode") ?? void 0,
418
+ errorMessage: searchParams.get("errorMessage") ?? void 0,
419
+ nonce: searchParams.get("nonce") ?? void 0,
420
+ phantomPublicKey: searchParams.get("phantom_encryption_public_key") ?? void 0,
421
+ requestId: searchParams.get("request_id") ?? void 0
422
+ };
423
+ };
424
+
425
+ //#endregion
426
+ //#region src/phantomRedirect/completePhantomRedirect/completePhantomRedirect.ts
427
+ const methodErrorEventMap = {
428
+ connect: "phantomRedirectConnectionError",
429
+ disconnect: "phantomRedirectDisconnectError",
430
+ signAllTransactions: "phantomRedirectSignAllTransactionsError",
431
+ signAndSendTransaction: "phantomRedirectSignAndSendTransactionError",
432
+ signMessage: "phantomRedirectSignMessageError",
433
+ signTransaction: "phantomRedirectSignTransactionError"
434
+ };
435
+ /**
436
+ * Returns true when the current JavaScript context is a **clone tab** —
437
+ * a new browser tab that Phantom opened to deliver the redirect callback on
438
+ * mobile browsers.
439
+ *
440
+ * ## Detection mechanism
441
+ *
442
+ * When a wallet operation is initiated (`connect`, `signMessage`, etc.)
443
+ * `setupPhantomListeners` sets `isOriginTab = true` on the per-client
444
+ * `phantomOriginTabService`. Because each browser tab (and each native mobile
445
+ * context) has its own JavaScript heap, the clone tab's client starts with
446
+ * `isOriginTab = false` and will never have it set to `true`.
447
+ *
448
+ * - `isOriginTab === false` → clone tab (mobile browser redirect) → should close
449
+ * - `isOriginTab === true` → originating tab or native mobile context → should stay open
450
+ */
451
+ const isCloneTab = (client) => !getPhantomOriginTab(client).isOriginTab;
452
+ /**
453
+ * Removes the pending request from storage, emits a Phantom redirect event to
454
+ * the local client, broadcasts it to the originating tab via `BroadcastChannel`,
455
+ * and — when running in a clone tab — emits `phantomRedirectCloseTab` so that
456
+ * the customer's `onCloseTab` callback can close the tab.
457
+ *
458
+ * This is the single point of truth for all cleanup and event delivery in the
459
+ * redirect flow. Every code path calls this exactly once, ensuring a consistent
460
+ * ordering: remove pending request → emit → broadcast → (maybe) close tab.
461
+ */
462
+ const completeAndEmitPhantomRedirectEvent = async ({ args, event }, client) => {
463
+ const core = (0, _dynamic_labs_sdk_client_core.getCore)(client);
464
+ const cloneTab = isCloneTab(client);
465
+ core.logger.debug("[PHANTOM] completeAndEmitPhantomRedirectEvent: start", {
466
+ event,
467
+ isCloneTab: cloneTab
468
+ });
469
+ await core.storage.removeItem(pendingRequestStorageKeySchema);
470
+ core.logger.debug("[PHANTOM] completeAndEmitPhantomRedirectEvent: emitting event locally", { event });
471
+ (0, _dynamic_labs_sdk_client_core.emitEvent)({
472
+ args,
473
+ event
474
+ }, client);
475
+ core.logger.debug("[PHANTOM] completeAndEmitPhantomRedirectEvent: broadcasting", { event });
476
+ broadcastPhantomEvent({
477
+ args,
478
+ event
479
+ }, client);
480
+ if (cloneTab) {
481
+ core.logger.debug("[PHANTOM] completeAndEmitPhantomRedirectEvent: emitting closeTab (clone tab)");
482
+ (0, _dynamic_labs_sdk_client_core.emitEvent)({
483
+ args: {},
484
+ event: "phantomRedirectCloseTab"
485
+ }, client);
486
+ }
487
+ };
488
+ /**
489
+ * Completes the Phantom wallet redirect flow after the deep link callback.
490
+ *
491
+ * This function is called on the page that Phantom redirects back to after the
492
+ * user approves or rejects a wallet operation. It processes the redirect URL,
493
+ * decrypts the response, updates session storage, and emits the appropriate
494
+ * events so that waiting callers (in this tab or the originating tab) can
495
+ * resolve or reject their pending promises.
496
+ *
497
+ * ## Cross-tab delivery
498
+ *
499
+ * On mobile browsers, Phantom opens the redirect URL in a **new tab** (the
500
+ * clone tab). Events are delivered to the originating tab via the
501
+ * `BroadcastChannel` API. Once delivery is complete this function emits
502
+ * `phantomRedirectCloseTab` so that the clone tab can be closed and the user
503
+ * is returned to the originating tab. See the `phantomRedirectCloseTab` event
504
+ * JSDoc for details on how to handle tab closing.
505
+ *
506
+ * @param params.url - The callback URL received from Phantom
507
+ * @param client - The Dynamic client instance
508
+ * @throws {NoPendingPhantomRequestError} If no pending request is found in storage
509
+ * @throws {PhantomMissingEncryptionParamsError} If the URL is missing the
510
+ * required encryption parameters (`phantom_encryption_public_key`, `data`,
511
+ * `nonce`) and does not carry an error code either
512
+ * @throws {PhantomRedirectRejectedError} If the user rejected the request in Phantom
513
+ */
514
+ const completePhantomRedirect = async ({ url }, client = (0, _dynamic_labs_sdk_client_core.getDefaultClient)()) => {
515
+ const core = (0, _dynamic_labs_sdk_client_core.getCore)(client);
516
+ core.logger.debug("[PHANTOM] completePhantomRedirect: start", { search: url.search });
517
+ const params = parsePhantomRedirectParams({ url });
518
+ const pendingRequest = await core.storage.getItem(pendingRequestStorageKeySchema);
519
+ core.logger.debug("[PHANTOM] completePhantomRedirect: pendingRequest", {
520
+ found: !!pendingRequest,
521
+ method: pendingRequest?.method
522
+ });
523
+ if (!pendingRequest) throw new NoPendingPhantomRequestError();
524
+ if (params.errorCode) {
525
+ const error = new PhantomRedirectRejectedError({
526
+ errorCode: params.errorCode,
527
+ errorMessage: params.errorMessage
528
+ });
529
+ const event = methodErrorEventMap[pendingRequest.method];
530
+ await completeAndEmitPhantomRedirectEvent({
531
+ args: { error },
532
+ event
533
+ }, client);
534
+ return;
535
+ }
536
+ if (pendingRequest.method === "disconnect") {
537
+ await completeAndEmitPhantomRedirectEvent({
538
+ args: {},
539
+ event: "phantomRedirectDisconnectComplete"
540
+ }, client);
541
+ return;
542
+ }
543
+ if (!params.data || !params.nonce) {
544
+ await core.storage.removeItem(pendingRequestStorageKeySchema);
545
+ throw new PhantomMissingEncryptionParamsError();
546
+ }
547
+ let sharedSecret;
548
+ if (pendingRequest.method === "connect") {
549
+ if (!params.phantomPublicKey) throw new PhantomMissingEncryptionParamsError();
550
+ sharedSecret = createNaClSharedSecret({
551
+ ourSecretKey: pendingRequest.dappSecretKey,
552
+ theirPublicKey: params.phantomPublicKey
553
+ });
554
+ } else {
555
+ const session = await core.storage.getItem(phantomSessionStorageKeySchema);
556
+ if (!session) throw new NoPhantomSessionError();
557
+ sharedSecret = session.sharedSecret;
558
+ }
559
+ const decryptedData = decryptPayload({
560
+ data: params.data,
561
+ nonce: params.nonce,
562
+ sharedSecret
563
+ });
564
+ if (pendingRequest.method === "connect") {
565
+ const connectData = decryptedData;
566
+ await core.storage.setItem(phantomSessionStorageKeySchema, {
567
+ dappPublicKey: pendingRequest.dappPublicKey,
568
+ dappSecretKey: pendingRequest.dappSecretKey,
569
+ phantomPublicKey: params.phantomPublicKey,
570
+ sessionToken: connectData.session,
571
+ sharedSecret,
572
+ walletAddress: connectData.public_key
573
+ });
574
+ await completeAndEmitPhantomRedirectEvent({
575
+ args: {
576
+ address: connectData.public_key,
577
+ publicKey: connectData.public_key
578
+ },
579
+ event: "phantomRedirectConnectionComplete"
580
+ }, client);
581
+ } else if (pendingRequest.method === "signMessage") {
582
+ const signData = decryptedData;
583
+ await completeAndEmitPhantomRedirectEvent({
584
+ args: {
585
+ message: pendingRequest.message,
586
+ signature: signData.signature
587
+ },
588
+ event: "phantomRedirectSignMessageComplete"
589
+ }, client);
590
+ } else if (pendingRequest.method === "signTransaction") await completeAndEmitPhantomRedirectEvent({
591
+ args: { transaction: decryptedData.transaction },
592
+ event: "phantomRedirectSignTransactionComplete"
593
+ }, client);
594
+ else if (pendingRequest.method === "signAllTransactions") await completeAndEmitPhantomRedirectEvent({
595
+ args: { transactions: decryptedData.transactions },
596
+ event: "phantomRedirectSignAllTransactionsComplete"
597
+ }, client);
598
+ else await completeAndEmitPhantomRedirectEvent({
599
+ args: { signature: decryptedData.signature },
600
+ event: "phantomRedirectSignAndSendTransactionComplete"
601
+ }, client);
602
+ };
603
+
604
+ //#endregion
605
+ //#region src/phantomRedirect/utils/buildPhantomDeepLink/buildPhantomDeepLink.ts
606
+ /**
607
+ * Builds a Phantom wallet deep link URL for wallet operations.
608
+ *
609
+ * @param params.method - The operation method (connect, signMessage, signTransaction, etc.)
610
+ * @param params.appUrl - Optional dApp URL shown in Phantom's UI
611
+ * @param params.dappPublicKey - The dApp's base58-encoded public encryption key
612
+ * @param params.redirectUrl - The URL to redirect back to after the operation
613
+ * @param params.cluster - Optional Solana cluster (mainnet-beta, devnet, testnet)
614
+ * @param params.payload - Optional encrypted payload for signing operations
615
+ * @param params.nonce - Optional nonce for encrypted payload
616
+ * @returns The complete Phantom deep link URL
617
+ */
618
+ const buildPhantomDeepLink = ({ appUrl, cluster, dappPublicKey, method, nonce, payload, redirectUrl }) => {
619
+ const url = new URL(`${PHANTOM_DEEPLINK_BASE_URL}/${method}`);
620
+ url.searchParams.set("dapp_encryption_public_key", dappPublicKey);
621
+ url.searchParams.set("redirect_link", redirectUrl);
622
+ if (appUrl) url.searchParams.set("app_url", appUrl);
623
+ if (cluster) url.searchParams.set("cluster", cluster);
624
+ if (payload) url.searchParams.set("payload", payload);
625
+ if (nonce) url.searchParams.set("nonce", nonce);
626
+ return url;
627
+ };
628
+
629
+ //#endregion
630
+ //#region src/phantomRedirect/utils/crypto/encryptPayload/encryptPayload.ts
631
+ /**
632
+ * Encrypts a payload using NaCl box encryption with a shared secret.
633
+ *
634
+ * @param params.payload - The payload object to encrypt
635
+ * @param params.sharedSecret - The base58-encoded shared secret
636
+ * @returns The encrypted data and nonce, both base58-encoded
637
+ */
638
+ const encryptPayload = ({ payload, sharedSecret }) => {
639
+ const nonce = tweetnacl.default.randomBytes(tweetnacl.default.box.nonceLength);
640
+ const payloadString = JSON.stringify(payload);
641
+ const payloadBytes = new Uint8Array((0, _dynamic_labs_sdk_client_core.getBuffer)().from(payloadString, "utf8"));
642
+ const encrypted = tweetnacl.default.box.after(payloadBytes, nonce, bs58.default.decode(sharedSecret));
643
+ return {
644
+ data: bs58.default.encode(encrypted),
645
+ nonce: bs58.default.encode(nonce)
646
+ };
647
+ };
648
+
649
+ //#endregion
650
+ //#region src/phantomRedirect/utils/crypto/generateNaClKeyPair/generateNaClKeyPair.ts
651
+ /**
652
+ * Generates a new NaCl key pair for encryption.
653
+ *
654
+ * @returns A key pair with base58-encoded public and secret keys
655
+ */
656
+ const generateNaClKeyPair = () => {
657
+ const keyPair = tweetnacl.default.box.keyPair();
658
+ return {
659
+ publicKey: bs58.default.encode(keyPair.publicKey),
660
+ secretKey: bs58.default.encode(keyPair.secretKey)
661
+ };
662
+ };
663
+
664
+ //#endregion
665
+ //#region src/phantomRedirect/utils/getPhantomCluster/getPhantomCluster.ts
666
+ /**
667
+ * Normalizes a cluster string to the value expected by Phantom's deep link protocol.
668
+ * Our API returns "mainnet" but Phantom expects "mainnet-beta".
669
+ */
670
+ const normalizeCluster = (cluster) => {
671
+ if (cluster === "mainnet") return "mainnet-beta";
672
+ return cluster;
673
+ };
674
+ /**
675
+ * Returns the Solana cluster name expected by Phantom's deep link protocol
676
+ * (e.g. "mainnet-beta", "devnet", "testnet").
677
+ *
678
+ * - When a `walletAccount` is provided, reads the cluster from the active network
679
+ * data for that account.
680
+ * - When no `walletAccount` is provided (e.g. during `connect` before an account
681
+ * exists), falls back to the first registered SOL network provider's cluster.
682
+ *
683
+ * Returns `undefined` if no cluster can be determined; Phantom will use the
684
+ * wallet's default in that case.
685
+ */
686
+ const getPhantomCluster = async ({ dynamicClient, walletAccount }) => {
687
+ if (walletAccount) {
688
+ const { networkData } = await (0, _dynamic_labs_sdk_client.getActiveNetworkData)({ walletAccount }, dynamicClient);
689
+ return normalizeCluster(networkData?.cluster);
690
+ }
691
+ return normalizeCluster((0, _dynamic_labs_sdk_client_core.getNetworkProviders)(dynamicClient).find((p) => p.chain === "SOL")?.cluster);
692
+ };
693
+
694
+ //#endregion
695
+ //#region src/phantomRedirect/utils/listenForPhantomBroadcast/listenForPhantomBroadcast.ts
696
+ /**
697
+ * Registers listeners for Phantom redirect events broadcast from other tabs
698
+ * (e.g. the redirect-completion tab), using the crossTabBroadcast service.
699
+ *
700
+ * Returns a cleanup function that unregisters all listeners — call it when the
701
+ * operation is no longer pending (e.g. in a promise `.finally()`).
702
+ *
703
+ * @param listeners - Map of event names to handler functions
704
+ * @param client - The Dynamic client instance
705
+ * @returns Cleanup function that removes all registered listeners
706
+ */
707
+ const listenForPhantomBroadcast = (listeners, client) => {
708
+ const { crossTabBroadcast } = (0, _dynamic_labs_sdk_client_core.getCore)(client);
709
+ const wrappedListeners = Object.entries(listeners).map(([event, listener]) => {
710
+ const wrapped = (args) => {
711
+ listener(args);
712
+ };
713
+ crossTabBroadcast.on(event, wrapped);
714
+ return {
715
+ event,
716
+ wrapped
717
+ };
718
+ });
719
+ return () => {
720
+ wrappedListeners.forEach(({ event, wrapped }) => {
721
+ crossTabBroadcast.off(event, wrapped);
722
+ });
723
+ };
724
+ };
725
+
726
+ //#endregion
727
+ //#region src/phantomRedirect/createPhantomRedirectWalletProvider/createPhantomRedirectWalletProvider.ts
728
+ /**
729
+ * Generates a random alphanumeric string of specified length.
730
+ */
731
+ const randomString = (length) => {
732
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
733
+ const bytes = crypto.getRandomValues(new Uint8Array(length));
734
+ return Array.from(bytes, (byte) => chars[byte % 62]).join("");
735
+ };
736
+ /**
737
+ * Extracts the dApp URL from a redirect URL.
738
+ */
739
+ const extractDappUrl = (redirectUrl) => {
740
+ const url = new URL(redirectUrl);
741
+ return `${url.protocol}//${url.host}`;
742
+ };
743
+ /**
744
+ * Creates a Phantom redirect-based Solana wallet provider.
745
+ *
746
+ * This wallet provider uses Phantom's deep link protocol for mobile wallet
747
+ * interactions with end-to-end encryption using NaCl.
748
+ *
749
+ * @param params.dynamicClient - The Dynamic client instance
750
+ * @returns A Phantom redirect wallet provider
751
+ */
752
+ const createPhantomRedirectWalletProvider = ({ baseRedirectUrl, dynamicClient }) => {
753
+ const core = (0, _dynamic_labs_sdk_client_core.getCore)(dynamicClient);
754
+ const walletProviderType = _dynamic_labs_sdk_api_core.WalletProviderEnum.DeepLink;
755
+ const key = (0, _dynamic_labs_sdk_client_core.formatWalletProviderKey)({
756
+ chain: "SOL",
757
+ displayName: "Phantom",
758
+ walletProviderType
759
+ });
760
+ const groupKey = (0, _dynamic_labs_sdk_client_core.formatWalletProviderGroupKey)("Phantom");
761
+ const metadata = {
762
+ displayName: "Phantom",
763
+ icon: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDgiIGhlaWdodD0iMTA4IiB2aWV3Qm94PSIwIDAgMTA4IDEwOCIgZmlsbD0ibm9uZSI+CjxyZWN0IHdpZHRoPSIxMDgiIGhlaWdodD0iMTA4IiByeD0iMjYiIGZpbGw9IiNBQjlGRjIiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00Ni41MjY3IDY5LjkyMjlDNDIuMDA1NCA3Ni44NTA5IDM0LjQyOTIgODUuNjE4MiAyNC4zNDggODUuNjE4MkMxOS41ODI0IDg1LjYxODIgMTUgODMuNjU2MyAxNSA3NS4xMzQyQzE1IDUzLjQzMDUgNDQuNjMyNiAxOS44MzI3IDcyLjEyNjggMTkuODMyN0M4Ny43NjggMTkuODMyNyA5NCAzMC42ODQ2IDk0IDQzLjAwNzlDOTQgNTguODI1OCA4My43MzU1IDc2LjkxMjIgNzMuNTMyMSA3Ni45MTIyQzcwLjI5MzkgNzYuOTEyMiA2OC43MDUzIDc1LjEzNDIgNjguNzA1MyA3Mi4zMTRDNjguNzA1MyA3MS41NzgzIDY4LjgyNzUgNzAuNzgxMiA2OS4wNzE5IDY5LjkyMjlDNjUuNTg5MyA3NS44Njk5IDU4Ljg2ODUgODEuMzg3OCA1Mi41NzU0IDgxLjM4NzhDNDcuOTkzIDgxLjM4NzggNDUuNjcxMyA3OC41MDYzIDQ1LjY3MTMgNzQuNDU5OEM0NS42NzEzIDcyLjk4ODQgNDUuOTc2OCA3MS40NTU2IDQ2LjUyNjcgNjkuOTIyOVpNODMuNjc2MSA0Mi41Nzk0QzgzLjY3NjEgNDYuMTcwNCA4MS41NTc1IDQ3Ljk2NTggNzkuMTg3NSA0Ny45NjU4Qzc2Ljc4MTYgNDcuOTY1OCA3NC42OTg5IDQ2LjE3MDQgNzQuNjk4OSA0Mi41Nzk0Qzc0LjY5ODkgMzguOTg4NSA3Ni43ODE2IDM3LjE5MzEgNzkuMTg3NSAzNy4xOTMxQzgxLjU1NzUgMzcuMTkzMSA4My42NzYxIDM4Ljk4ODUgODMuNjc2MSA0Mi41Nzk0Wk03MC4yMTAzIDQyLjU3OTVDNzAuMjEwMyA0Ni4xNzA0IDY4LjA5MTYgNDcuOTY1OCA2NS43MjE2IDQ3Ljk2NThDNjMuMzE1NyA0Ny45NjU4IDYxLjIzMyA0Ni4xNzA0IDYxLjIzMyA0Mi41Nzk1QzYxLjIzMyAzOC45ODg1IDYzLjMxNTcgMzcuMTkzMSA2NS43MjE2IDM3LjE5MzFDNjguMDkxNiAzNy4xOTMxIDcwLjIxMDMgMzguOTg4NSA3MC4yMTAzIDQyLjU3OTVaIiBmaWxsPSIjRkZGREY4Ii8+Cjwvc3ZnPg=="
764
+ };
765
+ const getSession = async () => {
766
+ const session = await core.storage.getItem(phantomSessionStorageKeySchema);
767
+ if (!session) throw new NoPhantomSessionError();
768
+ return session;
769
+ };
770
+ const setPendingRequest = async (request) => {
771
+ await core.storage.setItem(pendingRequestStorageKeySchema, request);
772
+ };
773
+ /**
774
+ * Registers listeners for both delivery paths Phantom uses depending on platform:
775
+ * - In mobile native, we get redirected back to the same context, so onceEvent suffices.
776
+ * - In mobile browsers, we get redirected back to a new tab, so a BroadcastChannel listener
777
+ * is also needed to receive the completion event from that tab.
778
+ *
779
+ * The broadcast channel is closed once the deferred promise settles.
780
+ */
781
+ const setupPhantomListeners = ({ completeEvent, deferredPromise, errorEvent, onComplete, onError }) => {
782
+ getPhantomOriginTab(dynamicClient).isOriginTab = true;
783
+ core.logger.debug("[PHANTOM] setupPhantomListeners: isOriginTab=true, registering listeners", {
784
+ completeEvent,
785
+ errorEvent
786
+ });
787
+ (0, _dynamic_labs_sdk_client.onceEvent)({
788
+ event: completeEvent,
789
+ listener: onComplete
790
+ }, dynamicClient);
791
+ (0, _dynamic_labs_sdk_client.onceEvent)({
792
+ event: errorEvent,
793
+ listener: onError
794
+ }, dynamicClient);
795
+ const closeChannel = listenForPhantomBroadcast({
796
+ [completeEvent]: onComplete,
797
+ [errorEvent]: onError
798
+ }, dynamicClient);
799
+ deferredPromise.promise.finally(() => {
800
+ core.logger.debug("[PHANTOM] setupPhantomListeners: deferred promise settled, closing channel");
801
+ closeChannel();
802
+ }).catch(() => {});
803
+ };
804
+ const connect = async () => {
805
+ core.logger.debug("[PHANTOM] connect: start");
806
+ const redirectUrl = baseRedirectUrl;
807
+ const { publicKey: dappPublicKey, secretKey: dappSecretKey } = generateNaClKeyPair();
808
+ await setPendingRequest({
809
+ dappPublicKey,
810
+ dappSecretKey,
811
+ method: "connect",
812
+ requestId: randomString(32),
813
+ timestamp: Date.now()
814
+ });
815
+ core.logger.debug("[PHANTOM] connect: pending request stored, setting up listeners");
816
+ const deferredPromise = (0, _dynamic_labs_sdk_client_core.createDeferredPromise)();
817
+ setupPhantomListeners({
818
+ completeEvent: "phantomRedirectConnectionComplete",
819
+ deferredPromise,
820
+ errorEvent: "phantomRedirectConnectionError",
821
+ onComplete: ({ address, publicKey }) => {
822
+ core.logger.debug("[PHANTOM] connect: onComplete called", { address });
823
+ deferredPromise.resolve({ addresses: [{
824
+ address,
825
+ publicKey
826
+ }] });
827
+ },
828
+ onError: ({ error }) => {
829
+ core.logger.debug("[PHANTOM] connect: onError called", { error });
830
+ deferredPromise.reject(error);
831
+ }
832
+ });
833
+ const cluster = await getPhantomCluster({ dynamicClient });
834
+ const deepLinkUrl = buildPhantomDeepLink({
835
+ appUrl: extractDappUrl(redirectUrl),
836
+ cluster,
837
+ dappPublicKey,
838
+ method: "connect",
839
+ redirectUrl
840
+ });
841
+ core.logger.debug("[PHANTOM] connect: opening deeplink", {
842
+ deepLinkUrl: deepLinkUrl.toString(),
843
+ redirectUrl
844
+ });
845
+ await core.openDeeplink(deepLinkUrl.toString());
846
+ core.logger.debug("[PHANTOM] connect: deeplink opened, awaiting deferred promise");
847
+ return deferredPromise.promise;
848
+ };
849
+ const disconnect = async () => {
850
+ const session = await getSession();
851
+ const redirectUrl = baseRedirectUrl;
852
+ const { data, nonce } = encryptPayload({
853
+ payload: { session: session.sessionToken },
854
+ sharedSecret: session.sharedSecret
855
+ });
856
+ const requestId = randomString(32);
857
+ await setPendingRequest({
858
+ dappPublicKey: session.dappPublicKey,
859
+ dappSecretKey: session.dappSecretKey,
860
+ method: "disconnect",
861
+ requestId,
862
+ timestamp: Date.now()
863
+ });
864
+ const deferredPromise = (0, _dynamic_labs_sdk_client_core.createDeferredPromise)();
865
+ setupPhantomListeners({
866
+ completeEvent: "phantomRedirectDisconnectComplete",
867
+ deferredPromise,
868
+ errorEvent: "phantomRedirectDisconnectError",
869
+ onComplete: async () => {
870
+ await core.storage.removeItem(phantomSessionStorageKeySchema);
871
+ deferredPromise.resolve();
872
+ },
873
+ onError: ({ error }) => {
874
+ deferredPromise.reject(error);
875
+ }
876
+ });
877
+ const deepLinkUrl = buildPhantomDeepLink({
878
+ appUrl: extractDappUrl(redirectUrl),
879
+ dappPublicKey: session.dappPublicKey,
880
+ method: "disconnect",
881
+ nonce,
882
+ payload: data,
883
+ redirectUrl
884
+ });
885
+ await core.openDeeplink(deepLinkUrl.toString());
886
+ return deferredPromise.promise;
887
+ };
888
+ const getActiveNetworkId = async () => (0, _dynamic_labs_sdk_client_core.getActiveNetworkIdFromLastKnownRegistry)({
889
+ client: dynamicClient,
890
+ walletProviderKey: key
891
+ });
892
+ const getConnectedAddresses = async () => {
893
+ return { addresses: [(await getSession()).walletAddress] };
894
+ };
895
+ const signMessage = async ({ message, walletAccount }) => {
896
+ (0, _dynamic_labs_sdk_client_core.assertDefined)(walletAccount, "Wallet account is required for Phantom redirect");
897
+ const redirectUrl = baseRedirectUrl;
898
+ const session = await getSession();
899
+ const { data, nonce } = encryptPayload({
900
+ payload: {
901
+ message: bs58.default.encode(new Uint8Array((0, _dynamic_labs_sdk_client_core.getBuffer)().from(message))),
902
+ session: session.sessionToken
903
+ },
904
+ sharedSecret: session.sharedSecret
905
+ });
906
+ const requestId = randomString(32);
907
+ await setPendingRequest({
908
+ dappPublicKey: session.dappPublicKey,
909
+ dappSecretKey: session.dappSecretKey,
910
+ message,
911
+ method: "signMessage",
912
+ requestId,
913
+ timestamp: Date.now(),
914
+ walletAddress: walletAccount.address
915
+ });
916
+ const deferredPromise = (0, _dynamic_labs_sdk_client_core.createDeferredPromise)();
917
+ setupPhantomListeners({
918
+ completeEvent: "phantomRedirectSignMessageComplete",
919
+ deferredPromise,
920
+ errorEvent: "phantomRedirectSignMessageError",
921
+ onComplete: ({ signature }) => {
922
+ deferredPromise.resolve({ signature });
923
+ },
924
+ onError: ({ error }) => {
925
+ deferredPromise.reject(error);
926
+ }
927
+ });
928
+ const cluster = await getPhantomCluster({
929
+ dynamicClient,
930
+ walletAccount
931
+ });
932
+ const deepLinkUrl = buildPhantomDeepLink({
933
+ appUrl: extractDappUrl(redirectUrl),
934
+ cluster,
935
+ dappPublicKey: session.dappPublicKey,
936
+ method: "signMessage",
937
+ nonce,
938
+ payload: data,
939
+ redirectUrl
940
+ });
941
+ await core.openDeeplink(deepLinkUrl.toString());
942
+ return deferredPromise.promise;
943
+ };
944
+ const signTransaction$1 = async ({ transaction, walletAccount }) => {
945
+ (0, _dynamic_labs_sdk_client_core.assertDefined)(walletAccount, "Wallet account is required for Phantom redirect");
946
+ const redirectUrl = baseRedirectUrl;
947
+ const session = await getSession();
948
+ const serialized = transaction instanceof _solana_web3_js.VersionedTransaction ? transaction.serialize() : transaction.serialize({
949
+ requireAllSignatures: false,
950
+ verifySignatures: false
951
+ });
952
+ const transactionBase58 = bs58.default.encode(new Uint8Array(serialized));
953
+ const { data, nonce } = encryptPayload({
954
+ payload: {
955
+ session: session.sessionToken,
956
+ transaction: transactionBase58
957
+ },
958
+ sharedSecret: session.sharedSecret
959
+ });
960
+ const requestId = randomString(32);
961
+ await setPendingRequest({
962
+ dappPublicKey: session.dappPublicKey,
963
+ dappSecretKey: session.dappSecretKey,
964
+ method: "signTransaction",
965
+ requestId,
966
+ timestamp: Date.now(),
967
+ walletAddress: walletAccount.address
968
+ });
969
+ const deferredPromise = (0, _dynamic_labs_sdk_client_core.createDeferredPromise)();
970
+ const deserializeTransaction = ({ transaction: signedTransactionBase58 }) => {
971
+ const decoded = bs58.default.decode(signedTransactionBase58);
972
+ const signedTransaction = transaction instanceof _solana_web3_js.VersionedTransaction ? _solana_web3_js.VersionedTransaction.deserialize(decoded) : _solana_web3_js.Transaction.from(decoded);
973
+ deferredPromise.resolve({ signedTransaction });
974
+ };
975
+ setupPhantomListeners({
976
+ completeEvent: "phantomRedirectSignTransactionComplete",
977
+ deferredPromise,
978
+ errorEvent: "phantomRedirectSignTransactionError",
979
+ onComplete: deserializeTransaction,
980
+ onError: ({ error }) => {
981
+ deferredPromise.reject(error);
982
+ }
983
+ });
984
+ const cluster = await getPhantomCluster({
985
+ dynamicClient,
986
+ walletAccount
987
+ });
988
+ const deepLinkUrl = buildPhantomDeepLink({
989
+ appUrl: extractDappUrl(redirectUrl),
990
+ cluster,
991
+ dappPublicKey: session.dappPublicKey,
992
+ method: "signTransaction",
993
+ nonce,
994
+ payload: data,
995
+ redirectUrl
996
+ });
997
+ await core.openDeeplink(deepLinkUrl.toString());
998
+ return deferredPromise.promise;
999
+ };
1000
+ const signAllTransactions$1 = async ({ transactions, walletAccount }) => {
1001
+ (0, _dynamic_labs_sdk_client_core.assertDefined)(walletAccount, "Wallet account is required for Phantom redirect");
1002
+ const redirectUrl = baseRedirectUrl;
1003
+ const session = await getSession();
1004
+ const transactionsBase58 = transactions.map((tx) => tx instanceof _solana_web3_js.VersionedTransaction ? tx.serialize() : tx.serialize({
1005
+ requireAllSignatures: false,
1006
+ verifySignatures: false
1007
+ })).map((s) => bs58.default.encode(new Uint8Array(s)));
1008
+ const { data, nonce } = encryptPayload({
1009
+ payload: {
1010
+ session: session.sessionToken,
1011
+ transactions: transactionsBase58
1012
+ },
1013
+ sharedSecret: session.sharedSecret
1014
+ });
1015
+ const requestId = randomString(32);
1016
+ await setPendingRequest({
1017
+ dappPublicKey: session.dappPublicKey,
1018
+ dappSecretKey: session.dappSecretKey,
1019
+ method: "signAllTransactions",
1020
+ requestId,
1021
+ timestamp: Date.now(),
1022
+ walletAddress: walletAccount.address
1023
+ });
1024
+ const deferredPromise = (0, _dynamic_labs_sdk_client_core.createDeferredPromise)();
1025
+ const deserializeTransactions = ({ transactions: signedTransactionsBase58 }) => {
1026
+ const signedTransactions = signedTransactionsBase58.map((txBase58, i) => {
1027
+ const decoded = bs58.default.decode(txBase58);
1028
+ return transactions[i] instanceof _solana_web3_js.VersionedTransaction ? _solana_web3_js.VersionedTransaction.deserialize(decoded) : _solana_web3_js.Transaction.from(decoded);
1029
+ });
1030
+ deferredPromise.resolve({ signedTransactions });
1031
+ };
1032
+ setupPhantomListeners({
1033
+ completeEvent: "phantomRedirectSignAllTransactionsComplete",
1034
+ deferredPromise,
1035
+ errorEvent: "phantomRedirectSignAllTransactionsError",
1036
+ onComplete: deserializeTransactions,
1037
+ onError: ({ error }) => {
1038
+ deferredPromise.reject(error);
1039
+ }
1040
+ });
1041
+ const cluster = await getPhantomCluster({
1042
+ dynamicClient,
1043
+ walletAccount
1044
+ });
1045
+ const deepLinkUrl = buildPhantomDeepLink({
1046
+ appUrl: extractDappUrl(redirectUrl),
1047
+ cluster,
1048
+ dappPublicKey: session.dappPublicKey,
1049
+ method: "signAllTransactions",
1050
+ nonce,
1051
+ payload: data,
1052
+ redirectUrl
1053
+ });
1054
+ await core.openDeeplink(deepLinkUrl.toString());
1055
+ return deferredPromise.promise;
1056
+ };
1057
+ const signAndSendTransaction$1 = async ({ options, transaction, walletAccount }) => {
1058
+ const { signedTransaction } = await signTransaction$1({
1059
+ transaction,
1060
+ walletAccount
1061
+ });
1062
+ const { networkData } = await (0, _dynamic_labs_sdk_client.getActiveNetworkData)({ walletAccount }, dynamicClient);
1063
+ (0, _dynamic_labs_sdk_client_core.assertDefined)(networkData, "Network data is required to broadcast transaction");
1064
+ const connection = require_solanaTransferAmount.getSolanaConnection({ networkData });
1065
+ const rawTransaction = signedTransaction.serialize();
1066
+ return { signature: await connection.sendRawTransaction(rawTransaction, options) };
1067
+ };
1068
+ return {
1069
+ chain: "SOL",
1070
+ connect,
1071
+ disconnect,
1072
+ executeCheckoutTransaction: (args) => require_solanaTransferAmount.solanaExecuteCheckoutTransaction(args, dynamicClient),
1073
+ getActiveNetworkId,
1074
+ getConnectedAddresses,
1075
+ groupKey,
1076
+ key,
1077
+ metadata,
1078
+ signAllTransactions: signAllTransactions$1,
1079
+ signAndSendTransaction: signAndSendTransaction$1,
1080
+ signMessage,
1081
+ signTransaction: signTransaction$1,
1082
+ transferAmount: (args) => require_solanaTransferAmount.solanaTransferAmount(args, dynamicClient),
1083
+ walletProviderType
1084
+ };
1085
+ };
1086
+
1087
+ //#endregion
1088
+ //#region src/phantomRedirect/detectPhantomRedirect/detectPhantomRedirect.ts
1089
+ /**
1090
+ * Detects if the current URL is a Phantom wallet redirect.
1091
+ *
1092
+ * This function examines the URL parameters to determine if it contains
1093
+ * redirect data from a Phantom wallet deep link operation, and validates
1094
+ * that there is a corresponding pending request in storage.
1095
+ *
1096
+ * @param params.url - The URL to check for Phantom redirect parameters
1097
+ * @param client - The Dynamic client instance
1098
+ * @returns A promise that resolves to true if the URL is a valid Phantom redirect, false otherwise
1099
+ */
1100
+ const detectPhantomRedirect = async ({ url }, client = (0, _dynamic_labs_sdk_client_core.getDefaultClient)()) => {
1101
+ const core = (0, _dynamic_labs_sdk_client_core.getCore)(client);
1102
+ if (!(url.searchParams.has("phantom_encryption_public_key") || url.searchParams.has("errorCode") || url.searchParams.has("nonce") && url.searchParams.has("data"))) return false;
1103
+ await core.initTrack.waitForAll();
1104
+ const pendingRequest = await core.storage.getItem(pendingRequestStorageKeySchema);
1105
+ return Boolean(pendingRequest);
1106
+ };
1107
+
1108
+ //#endregion
1109
+ //#region src/phantomRedirect/addPhantomRedirectSolanaExtension/addPhantomRedirectSolanaExtension.ts
1110
+ const PHANTOM_REDIRECT_SOLANA_EXTENSION_KEY = "phantomRedirectSolana";
1111
+ /**
1112
+ * Adds the Phantom redirect Solana extension to the Dynamic client.
1113
+ *
1114
+ * ### What this extension does
1115
+ *
1116
+ * This extension enables Phantom wallet integration via deep link redirects,
1117
+ * designed for mobile environments where a browser extension is not available.
1118
+ *
1119
+ * On initialization it:
1120
+ * 1. Registers the internal Dynamic extension logic handlers.
1121
+ * 2. Detects whether the current URL is a Phantom redirect callback and, if
1122
+ * so, completes the pending operation (decrypt response, emit events,
1123
+ * broadcast to originating tab).
1124
+ * 3. Sets up the `onCloseTab` listener so that the clone tab is closed after completion.
1125
+ *
1126
+ * ### Mobile browser redirect flow
1127
+ *
1128
+ * ```
1129
+ * [Tab 1 — your app] [Phantom app / PWA] [Tab 2 — clone]
1130
+ * connect()
1131
+ * openDeeplink(phantomUrl) ─────────────►
1132
+ * user approves
1133
+ * redirect to app ───────────────►
1134
+ * completePhantomRedirect()
1135
+ * broadcastPhantomEvent()
1136
+ * emits phantomRedirectCloseTab
1137
+ * onCloseTab() → window.close()
1138
+ * BroadcastChannel receives ◄──────────────────────────────────────────────
1139
+ * deferredPromise.resolve()
1140
+ * ```
1141
+ *
1142
+ * ### Mobile native flow (React Native / Capacitor)
1143
+ *
1144
+ * The deep link is delivered to the same JavaScript context, so `Tab 2` never
1145
+ * exists. `completePhantomRedirect` detects this via a `sessionStorage`
1146
+ * marker written during request initiation and does **not** emit
1147
+ * `phantomRedirectCloseTab`.
1148
+ *
1149
+ * @param params.url - The current page URL
1150
+ * @param params.onCloseTab - Callback invoked when the clone tab should close
1151
+ * @param params.disableAutoRedirectCompletion - Skip auto detection/completion
1152
+ * @param [client] - The Dynamic client. Only required for multiple clients.
1153
+ */
1154
+ const addPhantomRedirectSolanaExtension = async ({ disableAutoRedirectCompletion, onCloseTab, url }, client = (0, _dynamic_labs_sdk_client_core.getDefaultClient)()) => {
1155
+ if ((0, _dynamic_labs_sdk_client_core.hasExtension)({ extensionKey: PHANTOM_REDIRECT_SOLANA_EXTENSION_KEY }, client)) {
1156
+ (0, _dynamic_labs_sdk_client_core.getCore)(client).logger.debug("[PHANTOM] addPhantomRedirectSolanaExtension: already registered, skipping");
1157
+ return;
1158
+ }
1159
+ (0, _dynamic_labs_sdk_client_core.registerExtension)({ extensionKey: PHANTOM_REDIRECT_SOLANA_EXTENSION_KEY }, client);
1160
+ require_solanaTransferAmount.registerSolanaNetworkProviderBuilder(client);
1161
+ const core = (0, _dynamic_labs_sdk_client_core.getCore)(client);
1162
+ if (!disableAutoRedirectCompletion) {
1163
+ if (await detectPhantomRedirect({ url }, client)) {
1164
+ (0, _dynamic_labs_sdk_client.onceEvent)({
1165
+ event: "phantomRedirectCloseTab",
1166
+ listener: onCloseTab
1167
+ }, client);
1168
+ core.initTrack.track({
1169
+ name: "phantomRedirectCompletion",
1170
+ promise: completePhantomRedirect({ url }, client).catch((error) => {
1171
+ core.logger.debug("[PHANTOM] addPhantomRedirectSolanaExtension: completion failed", { error });
1172
+ core.logger.error("Phantom redirect completion failed:", error);
1173
+ })
1174
+ });
1175
+ }
1176
+ }
1177
+ const walletProvider = createPhantomRedirectWalletProvider({
1178
+ baseRedirectUrl: `${url.protocol}//${url.host}${url.pathname}`,
1179
+ dynamicClient: client
1180
+ });
1181
+ (0, _dynamic_labs_sdk_client_core.getWalletProviderRegistry)(client).register({
1182
+ priority: _dynamic_labs_sdk_client_core.WalletProviderPriority.WINDOW_INJECT,
1183
+ walletProvider
1184
+ });
230
1185
  };
231
1186
 
232
1187
  //#endregion
@@ -240,7 +1195,7 @@ const isSolanaWalletProvider = (provider) => {
240
1195
  */
241
1196
  const signAllTransactions = async ({ walletAccount, transactions }, client = (0, _dynamic_labs_sdk_client.getDefaultClient)()) => {
242
1197
  const provider = (0, _dynamic_labs_sdk_client_core.getWalletProviderFromWalletAccount)({ walletAccount }, client);
243
- if (!isSolanaWalletProvider(provider)) throw new NotSolanaProviderError({ providerKey: provider.key });
1198
+ if (!require_solanaTransferAmount.isSolanaWalletProvider(provider)) throw new require_solanaTransferAmount.NotSolanaProviderError({ providerKey: provider.key });
244
1199
  return provider.signAllTransactions({
245
1200
  transactions,
246
1201
  walletAccount
@@ -262,7 +1217,7 @@ const signAllTransactions = async ({ walletAccount, transactions }, client = (0,
262
1217
  */
263
1218
  const signAndSendSponsoredTransaction = async ({ walletAccount, transaction, options }, client = (0, _dynamic_labs_sdk_client.getDefaultClient)()) => {
264
1219
  const provider = (0, _dynamic_labs_sdk_client_core.getWalletProviderFromWalletAccount)({ walletAccount }, client);
265
- if (!isSolanaWalletProvider(provider)) throw new NotSolanaProviderError({ providerKey: provider.key });
1220
+ if (!require_solanaTransferAmount.isSolanaWalletProvider(provider)) throw new require_solanaTransferAmount.NotSolanaProviderError({ providerKey: provider.key });
266
1221
  if (!provider.signAndSendSponsoredTransaction) throw new _dynamic_labs_sdk_client_core.MethodNotImplementedError("signAndSendSponsoredTransaction");
267
1222
  return provider.signAndSendSponsoredTransaction({
268
1223
  options,
@@ -282,7 +1237,7 @@ const signAndSendSponsoredTransaction = async ({ walletAccount, transaction, opt
282
1237
  */
283
1238
  const signAndSendTransaction = async ({ walletAccount, transaction, options }, client = (0, _dynamic_labs_sdk_client.getDefaultClient)()) => {
284
1239
  const provider = (0, _dynamic_labs_sdk_client_core.getWalletProviderFromWalletAccount)({ walletAccount }, client);
285
- if (!isSolanaWalletProvider(provider)) throw new NotSolanaProviderError({ providerKey: provider.key });
1240
+ if (!require_solanaTransferAmount.isSolanaWalletProvider(provider)) throw new require_solanaTransferAmount.NotSolanaProviderError({ providerKey: provider.key });
286
1241
  return provider.signAndSendTransaction({
287
1242
  options,
288
1243
  transaction,
@@ -301,7 +1256,7 @@ const signAndSendTransaction = async ({ walletAccount, transaction, options }, c
301
1256
  */
302
1257
  const signTransaction = async ({ walletAccount, transaction }, client = (0, _dynamic_labs_sdk_client.getDefaultClient)()) => {
303
1258
  const provider = (0, _dynamic_labs_sdk_client_core.getWalletProviderFromWalletAccount)({ walletAccount }, client);
304
- if (!isSolanaWalletProvider(provider)) throw new NotSolanaProviderError({ providerKey: provider.key });
1259
+ if (!require_solanaTransferAmount.isSolanaWalletProvider(provider)) throw new require_solanaTransferAmount.NotSolanaProviderError({ providerKey: provider.key });
305
1260
  return provider.signTransaction({
306
1261
  transaction,
307
1262
  walletAccount
@@ -310,16 +1265,20 @@ const signTransaction = async ({ walletAccount, transaction }, client = (0, _dyn
310
1265
 
311
1266
  //#endregion
312
1267
  //#region src/exports/index.ts
313
- (0, _dynamic_labs_sdk_assert_package_version.assertPackageVersion)(require_isVersionedTransaction.name, require_isVersionedTransaction.version);
1268
+ (0, _dynamic_labs_sdk_assert_package_version.assertPackageVersion)(require_solanaTransferAmount.name, require_solanaTransferAmount.version);
314
1269
 
315
1270
  //#endregion
316
- exports.NotSolanaProviderError = NotSolanaProviderError;
1271
+ exports.NotSolanaProviderError = require_solanaTransferAmount.NotSolanaProviderError;
317
1272
  exports.SponsorTransactionError = require_addWaasSolanaExtension.SponsorTransactionError;
1273
+ exports.addPhantomRedirectSolanaExtension = addPhantomRedirectSolanaExtension;
318
1274
  exports.addSolanaExtension = addSolanaExtension;
319
1275
  exports.calculateSolanaTransactionFee = calculateSolanaTransactionFee;
320
- exports.getSolanaConnection = require_addWaasSolanaExtension.getSolanaConnection;
1276
+ exports.completePhantomRedirect = completePhantomRedirect;
1277
+ exports.detectPhantomRedirect = detectPhantomRedirect;
1278
+ exports.getSolanaConnection = require_solanaTransferAmount.getSolanaConnection;
1279
+ exports.isSolanaGasSponsorshipEnabled = require_solanaTransferAmount.isSolanaGasSponsorshipEnabled;
321
1280
  exports.isSolanaNetworkProvider = isSolanaNetworkProvider;
322
- exports.isSolanaWalletAccount = isSolanaWalletAccount;
1281
+ exports.isSolanaWalletAccount = require_solanaTransferAmount.isSolanaWalletAccount;
323
1282
  exports.signAllTransactions = signAllTransactions;
324
1283
  exports.signAndSendSponsoredTransaction = signAndSendSponsoredTransaction;
325
1284
  exports.signAndSendTransaction = signAndSendTransaction;