@pooflabs/web 0.0.68 → 0.0.69-rc.1
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/auth/index.d.ts +1 -0
- package/dist/auth/providers/solana-mobile-wallet-provider.d.ts +75 -0
- package/dist/{index-ChGj4uuO.js → index-BRZ4-fcO.js} +2 -2
- package/dist/{index-ChGj4uuO.js.map → index-BRZ4-fcO.js.map} +1 -1
- package/dist/{index-YzZ1QavD.js → index-C4TkISTV.js} +545 -10
- package/dist/index-C4TkISTV.js.map +1 -0
- package/dist/{index-DVa7oS4V.esm.js → index-DUIdAaPc.esm.js} +543 -11
- package/dist/index-DUIdAaPc.esm.js.map +1 -0
- package/dist/{index-CzcmQ2iE.esm.js → index-DnHUGqjI.esm.js} +2 -2
- package/dist/{index-CzcmQ2iE.esm.js.map → index-DnHUGqjI.esm.js.map} +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.esm.js +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/package.json +12 -2
- package/dist/index-DVa7oS4V.esm.js.map +0 -1
- package/dist/index-YzZ1QavD.js.map +0 -1
|
@@ -10777,7 +10777,10 @@ function handleServerMessage(connection, message) {
|
|
|
10777
10777
|
}
|
|
10778
10778
|
function notifyCallbacks(subscription, data) {
|
|
10779
10779
|
var _a;
|
|
10780
|
-
|
|
10780
|
+
// Snapshot the callbacks array so that unsubscriptions during
|
|
10781
|
+
// notification don't cause callbacks to be skipped.
|
|
10782
|
+
const callbacks = subscription.callbacks.slice();
|
|
10783
|
+
for (const callback of callbacks) {
|
|
10781
10784
|
try {
|
|
10782
10785
|
(_a = callback.onData) === null || _a === void 0 ? void 0 : _a.call(callback, data);
|
|
10783
10786
|
}
|
|
@@ -13563,7 +13566,7 @@ async function loadDependencies() {
|
|
|
13563
13566
|
const [reactModule, reactDomModule, phantomModule] = await Promise.all([
|
|
13564
13567
|
import('react'),
|
|
13565
13568
|
import('react-dom/client'),
|
|
13566
|
-
Promise.resolve().then(function () { return require('./index-
|
|
13569
|
+
Promise.resolve().then(function () { return require('./index-BRZ4-fcO.js'); })
|
|
13567
13570
|
]);
|
|
13568
13571
|
// Extract default export from ESM module namespace
|
|
13569
13572
|
// Dynamic import() returns { default: Module, ...exports }, not the module directly
|
|
@@ -13675,9 +13678,15 @@ class PhantomWalletProvider {
|
|
|
13675
13678
|
this.containerElement.setAttribute('data-phantom-provider', 'true');
|
|
13676
13679
|
// Keep Phantom UI above host overlays while avoiding global click-capture.
|
|
13677
13680
|
this.containerElement.style.position = 'fixed';
|
|
13678
|
-
this.containerElement.style.inset = '0';
|
|
13679
13681
|
this.containerElement.style.zIndex = '2147483647';
|
|
13680
|
-
this.
|
|
13682
|
+
if (this.config.enablePrivyFallback) {
|
|
13683
|
+
// Full-viewport overlay for custom modal; pointer-events: none lets
|
|
13684
|
+
// clicks pass through to page except where the modal sets 'auto'
|
|
13685
|
+
this.containerElement.style.inset = '0';
|
|
13686
|
+
this.containerElement.style.pointerEvents = 'none';
|
|
13687
|
+
}
|
|
13688
|
+
// When Privy fallback is off, the container just hosts PhantomProvider
|
|
13689
|
+
// without covering the viewport or blocking pointer events
|
|
13681
13690
|
document.body.appendChild(this.containerElement);
|
|
13682
13691
|
const that = this;
|
|
13683
13692
|
const { PhantomProvider: ReactPhantomProvider, usePhantom, useConnect, useDisconnect, useModal, useSolana, useDiscoveredWallets, AddressType, darkTheme, lightTheme } = phantomReactSdk;
|
|
@@ -34897,6 +34906,508 @@ class OffchainAuthProvider {
|
|
|
34897
34906
|
}
|
|
34898
34907
|
}
|
|
34899
34908
|
|
|
34909
|
+
/**
|
|
34910
|
+
* Detects whether the current environment is a mobile browser capable of
|
|
34911
|
+
* Mobile Wallet Adapter (MWA) communication.
|
|
34912
|
+
*
|
|
34913
|
+
* Returns true on Android browsers (Chrome, etc.) where MWA intents work,
|
|
34914
|
+
* or inside a Seeker/Saga in-app browser context.
|
|
34915
|
+
*/
|
|
34916
|
+
function isMobileWalletAvailable() {
|
|
34917
|
+
if (typeof window === 'undefined' || typeof navigator === 'undefined')
|
|
34918
|
+
return false;
|
|
34919
|
+
const ua = navigator.userAgent || '';
|
|
34920
|
+
// Android browser — MWA uses Android intents
|
|
34921
|
+
const isAndroid = /Android/i.test(ua);
|
|
34922
|
+
// In-app browser inside a wallet app on Seeker/Saga
|
|
34923
|
+
const isWalletInAppBrowser = /SolanaWallet/i.test(ua) || /SeedVault/i.test(ua);
|
|
34924
|
+
return isAndroid || isWalletInAppBrowser;
|
|
34925
|
+
}
|
|
34926
|
+
// Dynamically imported MWA module
|
|
34927
|
+
let mwaModule = null;
|
|
34928
|
+
let mwaLoadPromise = null;
|
|
34929
|
+
async function loadMwaModule() {
|
|
34930
|
+
if (mwaModule)
|
|
34931
|
+
return;
|
|
34932
|
+
if (typeof window === 'undefined')
|
|
34933
|
+
return;
|
|
34934
|
+
if (mwaLoadPromise)
|
|
34935
|
+
return mwaLoadPromise;
|
|
34936
|
+
mwaLoadPromise = (async () => {
|
|
34937
|
+
try {
|
|
34938
|
+
mwaModule = await import('@solana-mobile/wallet-adapter-mobile');
|
|
34939
|
+
}
|
|
34940
|
+
catch (e) {
|
|
34941
|
+
console.warn('[SolanaMobileWallet] @solana-mobile/wallet-adapter-mobile not installed. Install it to enable Seeker wallet support.');
|
|
34942
|
+
throw new Error('Missing @solana-mobile/wallet-adapter-mobile dependency');
|
|
34943
|
+
}
|
|
34944
|
+
})();
|
|
34945
|
+
return mwaLoadPromise;
|
|
34946
|
+
}
|
|
34947
|
+
/**
|
|
34948
|
+
* Registers Mobile Wallet Adapter as a wallet-standard wallet so it appears
|
|
34949
|
+
* in wallet selection UIs and can be discovered by other wallet-standard consumers.
|
|
34950
|
+
*
|
|
34951
|
+
* Call this once at app startup (in a browser-only / non-SSR context).
|
|
34952
|
+
*
|
|
34953
|
+
* @param config - App identity and optional remote host authority for desktop QR code support
|
|
34954
|
+
*/
|
|
34955
|
+
async function registerMobileWalletAdapter(config) {
|
|
34956
|
+
var _a;
|
|
34957
|
+
if (typeof window === 'undefined')
|
|
34958
|
+
return;
|
|
34959
|
+
try {
|
|
34960
|
+
const walletStandardMobile = await import('@solana-mobile/wallet-standard-mobile');
|
|
34961
|
+
const registerMwa = walletStandardMobile.registerMwa || ((_a = walletStandardMobile.default) === null || _a === void 0 ? void 0 : _a.registerMwa);
|
|
34962
|
+
if (!registerMwa) {
|
|
34963
|
+
console.warn('[SolanaMobileWallet] registerMwa not found in @solana-mobile/wallet-standard-mobile');
|
|
34964
|
+
return;
|
|
34965
|
+
}
|
|
34966
|
+
const options = {};
|
|
34967
|
+
if (config === null || config === void 0 ? void 0 : config.appIdentity) {
|
|
34968
|
+
options.appIdentity = config.appIdentity;
|
|
34969
|
+
}
|
|
34970
|
+
if (config === null || config === void 0 ? void 0 : config.chains) {
|
|
34971
|
+
options.chains = config.chains;
|
|
34972
|
+
}
|
|
34973
|
+
if (config === null || config === void 0 ? void 0 : config.remoteHostAuthority) {
|
|
34974
|
+
options.remoteHostAuthority = config.remoteHostAuthority;
|
|
34975
|
+
}
|
|
34976
|
+
// Use the library's default helpers if available
|
|
34977
|
+
if (walletStandardMobile.createDefaultAuthorizationCache) {
|
|
34978
|
+
options.authorizationCache = walletStandardMobile.createDefaultAuthorizationCache();
|
|
34979
|
+
}
|
|
34980
|
+
if (walletStandardMobile.createDefaultChainSelector) {
|
|
34981
|
+
options.chainSelector = walletStandardMobile.createDefaultChainSelector();
|
|
34982
|
+
}
|
|
34983
|
+
if (walletStandardMobile.createDefaultWalletNotFoundHandler) {
|
|
34984
|
+
options.onWalletNotFound = walletStandardMobile.createDefaultWalletNotFoundHandler();
|
|
34985
|
+
}
|
|
34986
|
+
registerMwa(options);
|
|
34987
|
+
}
|
|
34988
|
+
catch (e) {
|
|
34989
|
+
// @solana-mobile/wallet-standard-mobile is an optional dependency
|
|
34990
|
+
// Silently skip if not installed — the provider still works via
|
|
34991
|
+
// @solana-mobile/wallet-adapter-mobile directly
|
|
34992
|
+
console.debug('[SolanaMobileWallet] @solana-mobile/wallet-standard-mobile not available, skipping wallet-standard registration');
|
|
34993
|
+
}
|
|
34994
|
+
}
|
|
34995
|
+
/**
|
|
34996
|
+
* SolanaMobileWalletProvider implements the AuthProvider interface using the
|
|
34997
|
+
* Solana Mobile Wallet Adapter (MWA) protocol.
|
|
34998
|
+
*
|
|
34999
|
+
* This enables TaroBase dApps to work with any MWA-compliant wallet on Solana
|
|
35000
|
+
* mobile devices (Seeker, Saga) — including the native Seed Vault Wallet,
|
|
35001
|
+
* Phantom, Solflare, and any other wallet that implements the MWA protocol.
|
|
35002
|
+
*
|
|
35003
|
+
* The MWA protocol communicates with wallet apps via Android intents (on mobile)
|
|
35004
|
+
* or WebSocket relay (on desktop via QR code), eliminating the need to integrate
|
|
35005
|
+
* with each wallet individually.
|
|
35006
|
+
*/
|
|
35007
|
+
class SolanaMobileWalletProvider {
|
|
35008
|
+
constructor(networkUrl = null, config = {}) {
|
|
35009
|
+
this.mwaAdapter = null;
|
|
35010
|
+
this.authorizedPublicKey = null;
|
|
35011
|
+
this.networkUrl = networkUrl;
|
|
35012
|
+
this.config = config;
|
|
35013
|
+
if (typeof window === 'undefined') {
|
|
35014
|
+
throw new Error('SolanaMobileWalletProvider can only be instantiated in a browser environment');
|
|
35015
|
+
}
|
|
35016
|
+
if (SolanaMobileWalletProvider.instance) {
|
|
35017
|
+
return SolanaMobileWalletProvider.instance;
|
|
35018
|
+
}
|
|
35019
|
+
SolanaMobileWalletProvider.instance = this;
|
|
35020
|
+
}
|
|
35021
|
+
static getInstance(networkUrl, config) {
|
|
35022
|
+
if (!SolanaMobileWalletProvider.instance) {
|
|
35023
|
+
new SolanaMobileWalletProvider(networkUrl, config);
|
|
35024
|
+
}
|
|
35025
|
+
return SolanaMobileWalletProvider.instance;
|
|
35026
|
+
}
|
|
35027
|
+
async ensureAdapter() {
|
|
35028
|
+
var _a;
|
|
35029
|
+
if ((_a = this.mwaAdapter) === null || _a === void 0 ? void 0 : _a.connected)
|
|
35030
|
+
return this.mwaAdapter;
|
|
35031
|
+
await loadMwaModule();
|
|
35032
|
+
const { SolanaMobileWalletAdapter, createDefaultAddressSelector, createDefaultAuthorizationResultCache } = mwaModule;
|
|
35033
|
+
if (!this.mwaAdapter) {
|
|
35034
|
+
const cluster = this.config.cluster || 'mainnet-beta';
|
|
35035
|
+
this.mwaAdapter = new SolanaMobileWalletAdapter({
|
|
35036
|
+
addressSelector: createDefaultAddressSelector(),
|
|
35037
|
+
appIdentity: this.config.appIdentity || {
|
|
35038
|
+
name: 'TaroBase App',
|
|
35039
|
+
uri: typeof window !== 'undefined' ? window.location.origin : undefined,
|
|
35040
|
+
},
|
|
35041
|
+
authorizationResultCache: createDefaultAuthorizationResultCache(),
|
|
35042
|
+
cluster,
|
|
35043
|
+
});
|
|
35044
|
+
}
|
|
35045
|
+
return this.mwaAdapter;
|
|
35046
|
+
}
|
|
35047
|
+
async login() {
|
|
35048
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
35049
|
+
setAuthLoading(true);
|
|
35050
|
+
try {
|
|
35051
|
+
const adapter = await this.ensureAdapter();
|
|
35052
|
+
// Connect triggers the MWA authorization flow — this opens the wallet app
|
|
35053
|
+
// via Android intent and asks the user to authorize this dApp
|
|
35054
|
+
await adapter.connect();
|
|
35055
|
+
const publicKey = ((_b = (_a = adapter.publicKey) === null || _a === void 0 ? void 0 : _a.toBase58) === null || _b === void 0 ? void 0 : _b.call(_a)) || ((_d = (_c = adapter.publicKey) === null || _c === void 0 ? void 0 : _c.toString) === null || _d === void 0 ? void 0 : _d.call(_c));
|
|
35056
|
+
if (!publicKey) {
|
|
35057
|
+
throw new Error('No public key returned from wallet');
|
|
35058
|
+
}
|
|
35059
|
+
this.authorizedPublicKey = publicKey;
|
|
35060
|
+
// Check if we already have a valid session
|
|
35061
|
+
const existingSession = await WebSessionManager.getSession();
|
|
35062
|
+
if (existingSession && existingSession.address === publicKey) {
|
|
35063
|
+
const user = { provider: this, address: publicKey };
|
|
35064
|
+
setCurrentUser(user);
|
|
35065
|
+
return user;
|
|
35066
|
+
}
|
|
35067
|
+
// Create new session with signature
|
|
35068
|
+
const nonce = await genAuthNonce();
|
|
35069
|
+
const messageText = await genSolanaMessage(publicKey, nonce);
|
|
35070
|
+
// MWA signMessage expects Uint8Array
|
|
35071
|
+
const messageBytes = new TextEncoder().encode(messageText);
|
|
35072
|
+
const signatureBytes = await adapter.signMessage(messageBytes);
|
|
35073
|
+
const signature = bufferExports.Buffer.from(signatureBytes).toString('base64');
|
|
35074
|
+
const createSessionResult = await createSessionWithSignature(publicKey, messageText, signature);
|
|
35075
|
+
await WebSessionManager.storeSession(publicKey, createSessionResult.accessToken, createSessionResult.idToken, createSessionResult.refreshToken);
|
|
35076
|
+
// Mark auth method
|
|
35077
|
+
try {
|
|
35078
|
+
localStorage.setItem('tarobase_last_auth_method', 'mobile-wallet-adapter');
|
|
35079
|
+
}
|
|
35080
|
+
catch (_k) { }
|
|
35081
|
+
const user = { provider: this, address: publicKey };
|
|
35082
|
+
setCurrentUser(user);
|
|
35083
|
+
return user;
|
|
35084
|
+
}
|
|
35085
|
+
catch (error) {
|
|
35086
|
+
const isUserRejection = (error === null || error === void 0 ? void 0 : error.code) === 4001 ||
|
|
35087
|
+
((_e = error === null || error === void 0 ? void 0 : error.message) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('user rejected')) ||
|
|
35088
|
+
((_f = error === null || error === void 0 ? void 0 : error.message) === null || _f === void 0 ? void 0 : _f.toLowerCase().includes('user denied')) ||
|
|
35089
|
+
((_g = error === null || error === void 0 ? void 0 : error.message) === null || _g === void 0 ? void 0 : _g.toLowerCase().includes('user cancelled')) ||
|
|
35090
|
+
((_h = error === null || error === void 0 ? void 0 : error.message) === null || _h === void 0 ? void 0 : _h.toLowerCase().includes('user canceled')) ||
|
|
35091
|
+
((_j = error === null || error === void 0 ? void 0 : error.message) === null || _j === void 0 ? void 0 : _j.toLowerCase().includes('user declined'));
|
|
35092
|
+
if (!isUserRejection) {
|
|
35093
|
+
console.error('[SolanaMobileWallet] Login failed:', error);
|
|
35094
|
+
}
|
|
35095
|
+
throw error;
|
|
35096
|
+
}
|
|
35097
|
+
finally {
|
|
35098
|
+
setAuthLoading(false);
|
|
35099
|
+
}
|
|
35100
|
+
}
|
|
35101
|
+
async restoreSession() {
|
|
35102
|
+
const session = await WebSessionManager.getSession();
|
|
35103
|
+
if (session) {
|
|
35104
|
+
this.authorizedPublicKey = session.address;
|
|
35105
|
+
return { provider: this, address: session.address };
|
|
35106
|
+
}
|
|
35107
|
+
return null;
|
|
35108
|
+
}
|
|
35109
|
+
async logout() {
|
|
35110
|
+
var _a;
|
|
35111
|
+
try {
|
|
35112
|
+
if ((_a = this.mwaAdapter) === null || _a === void 0 ? void 0 : _a.connected) {
|
|
35113
|
+
await this.mwaAdapter.disconnect();
|
|
35114
|
+
}
|
|
35115
|
+
}
|
|
35116
|
+
catch (error) {
|
|
35117
|
+
console.error('[SolanaMobileWallet] Disconnect error:', error);
|
|
35118
|
+
}
|
|
35119
|
+
this.authorizedPublicKey = null;
|
|
35120
|
+
WebSessionManager.clearSession();
|
|
35121
|
+
setCurrentUser(null);
|
|
35122
|
+
}
|
|
35123
|
+
async signMessage(message) {
|
|
35124
|
+
var _a, _b;
|
|
35125
|
+
const adapter = await this.ensureAdapter();
|
|
35126
|
+
if (!adapter.connected) {
|
|
35127
|
+
await adapter.connect();
|
|
35128
|
+
}
|
|
35129
|
+
try {
|
|
35130
|
+
const messageBytes = new TextEncoder().encode(message);
|
|
35131
|
+
const signatureBytes = await adapter.signMessage(messageBytes);
|
|
35132
|
+
return bufferExports.Buffer.from(signatureBytes).toString('base64');
|
|
35133
|
+
}
|
|
35134
|
+
catch (error) {
|
|
35135
|
+
if (((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('not connected')) || ((_b = error === null || error === void 0 ? void 0 : error.message) === null || _b === void 0 ? void 0 : _b.includes('not authorized'))) {
|
|
35136
|
+
await this.logout();
|
|
35137
|
+
throw new Error('Wallet connection lost. Please reconnect.');
|
|
35138
|
+
}
|
|
35139
|
+
throw new Error(`Failed to sign message: ${error.message}`);
|
|
35140
|
+
}
|
|
35141
|
+
}
|
|
35142
|
+
async signTransaction(transaction) {
|
|
35143
|
+
var _a, _b;
|
|
35144
|
+
const adapter = await this.ensureAdapter();
|
|
35145
|
+
if (!adapter.connected) {
|
|
35146
|
+
await adapter.connect();
|
|
35147
|
+
}
|
|
35148
|
+
// Ensure blockhash is set
|
|
35149
|
+
const isLegacyTransaction = 'recentBlockhash' in transaction && !('message' in transaction && 'staticAccountKeys' in transaction.message);
|
|
35150
|
+
if (isLegacyTransaction) {
|
|
35151
|
+
const legacyTx = transaction;
|
|
35152
|
+
if (!legacyTx.recentBlockhash) {
|
|
35153
|
+
const rpcUrl = this.getRpcUrl();
|
|
35154
|
+
const connection = new web3_js.Connection(rpcUrl, 'confirmed');
|
|
35155
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
|
|
35156
|
+
legacyTx.recentBlockhash = blockhash;
|
|
35157
|
+
legacyTx.lastValidBlockHeight = lastValidBlockHeight;
|
|
35158
|
+
}
|
|
35159
|
+
if (!legacyTx.feePayer && adapter.publicKey) {
|
|
35160
|
+
legacyTx.feePayer = adapter.publicKey;
|
|
35161
|
+
}
|
|
35162
|
+
}
|
|
35163
|
+
else {
|
|
35164
|
+
const versionedTx = transaction;
|
|
35165
|
+
if (!versionedTx.message.recentBlockhash) {
|
|
35166
|
+
const rpcUrl = this.getRpcUrl();
|
|
35167
|
+
const connection = new web3_js.Connection(rpcUrl, 'confirmed');
|
|
35168
|
+
const { blockhash } = await connection.getLatestBlockhash('confirmed');
|
|
35169
|
+
versionedTx.message.recentBlockhash = blockhash;
|
|
35170
|
+
}
|
|
35171
|
+
}
|
|
35172
|
+
try {
|
|
35173
|
+
const signed = await adapter.signTransaction(transaction);
|
|
35174
|
+
return signed;
|
|
35175
|
+
}
|
|
35176
|
+
catch (error) {
|
|
35177
|
+
if (((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('not connected')) || ((_b = error === null || error === void 0 ? void 0 : error.message) === null || _b === void 0 ? void 0 : _b.includes('not authorized'))) {
|
|
35178
|
+
await this.logout();
|
|
35179
|
+
throw new Error('Wallet connection lost. Please reconnect.');
|
|
35180
|
+
}
|
|
35181
|
+
throw new Error(`Failed to sign transaction: ${error.message}`);
|
|
35182
|
+
}
|
|
35183
|
+
}
|
|
35184
|
+
async signAndSubmitTransaction(transaction, feePayer) {
|
|
35185
|
+
var _a, _b, _c, _d, _e, _f;
|
|
35186
|
+
const adapter = await this.ensureAdapter();
|
|
35187
|
+
if (!adapter.connected) {
|
|
35188
|
+
await adapter.connect();
|
|
35189
|
+
}
|
|
35190
|
+
const rpcUrl = this.getRpcUrl();
|
|
35191
|
+
const connection = new web3_js.Connection(rpcUrl, 'confirmed');
|
|
35192
|
+
const isSurfnet = rpcUrl === SURFNET_RPC_URL;
|
|
35193
|
+
try {
|
|
35194
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
|
|
35195
|
+
const isLegacyTransaction = 'recentBlockhash' in transaction && !('message' in transaction && 'staticAccountKeys' in transaction.message);
|
|
35196
|
+
if (isLegacyTransaction) {
|
|
35197
|
+
const legacyTx = transaction;
|
|
35198
|
+
legacyTx.recentBlockhash = blockhash;
|
|
35199
|
+
legacyTx.lastValidBlockHeight = lastValidBlockHeight;
|
|
35200
|
+
if (!legacyTx.feePayer) {
|
|
35201
|
+
if (feePayer) {
|
|
35202
|
+
legacyTx.feePayer = feePayer;
|
|
35203
|
+
}
|
|
35204
|
+
else if (adapter.publicKey) {
|
|
35205
|
+
legacyTx.feePayer = adapter.publicKey;
|
|
35206
|
+
}
|
|
35207
|
+
}
|
|
35208
|
+
}
|
|
35209
|
+
else {
|
|
35210
|
+
const versionedTx = transaction;
|
|
35211
|
+
versionedTx.message.recentBlockhash = blockhash;
|
|
35212
|
+
}
|
|
35213
|
+
// On surfnet, sign then submit manually
|
|
35214
|
+
if (isSurfnet) {
|
|
35215
|
+
const signedTx = await adapter.signTransaction(transaction);
|
|
35216
|
+
const signature = await connection.sendRawTransaction(signedTx.serialize(), {
|
|
35217
|
+
preflightCommitment: 'confirmed'
|
|
35218
|
+
});
|
|
35219
|
+
const confirmation = await connection.confirmTransaction({
|
|
35220
|
+
signature,
|
|
35221
|
+
blockhash,
|
|
35222
|
+
lastValidBlockHeight,
|
|
35223
|
+
}, 'confirmed');
|
|
35224
|
+
if (confirmation.value.err) {
|
|
35225
|
+
throw new Error(`Transaction failed: ${confirmation.value.err.toString()}`);
|
|
35226
|
+
}
|
|
35227
|
+
return signature;
|
|
35228
|
+
}
|
|
35229
|
+
// MWA supports signAndSendTransaction natively — this lets the wallet
|
|
35230
|
+
// app submit the transaction directly, which is more reliable on mobile
|
|
35231
|
+
if (adapter.sendTransaction) {
|
|
35232
|
+
const signature = await adapter.sendTransaction(transaction, connection, {
|
|
35233
|
+
preflightCommitment: 'confirmed',
|
|
35234
|
+
});
|
|
35235
|
+
await confirmAndCheckTransaction(connection, signature);
|
|
35236
|
+
return signature;
|
|
35237
|
+
}
|
|
35238
|
+
// Fallback: sign then submit
|
|
35239
|
+
const signedTx = await adapter.signTransaction(transaction);
|
|
35240
|
+
const signature = await connection.sendRawTransaction(signedTx.serialize(), {
|
|
35241
|
+
preflightCommitment: 'confirmed'
|
|
35242
|
+
});
|
|
35243
|
+
await confirmAndCheckTransaction(connection, signature);
|
|
35244
|
+
return signature;
|
|
35245
|
+
}
|
|
35246
|
+
catch (error) {
|
|
35247
|
+
if (((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('not connected')) || ((_b = error === null || error === void 0 ? void 0 : error.message) === null || _b === void 0 ? void 0 : _b.includes('not authorized'))) {
|
|
35248
|
+
await this.logout();
|
|
35249
|
+
throw new Error('Wallet connection lost. Please reconnect.');
|
|
35250
|
+
}
|
|
35251
|
+
const isUserRejection = (error === null || error === void 0 ? void 0 : error.code) === 4001 ||
|
|
35252
|
+
((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.toLowerCase().includes('user rejected')) ||
|
|
35253
|
+
((_d = error === null || error === void 0 ? void 0 : error.message) === null || _d === void 0 ? void 0 : _d.toLowerCase().includes('user denied')) ||
|
|
35254
|
+
((_e = error === null || error === void 0 ? void 0 : error.message) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('user cancelled')) ||
|
|
35255
|
+
((_f = error === null || error === void 0 ? void 0 : error.message) === null || _f === void 0 ? void 0 : _f.toLowerCase().includes('user canceled'));
|
|
35256
|
+
if (!isUserRejection) {
|
|
35257
|
+
console.error('[SolanaMobileWallet] Transaction failed:', error);
|
|
35258
|
+
}
|
|
35259
|
+
throw new Error(`Failed to execute transaction: ${error.message}`);
|
|
35260
|
+
}
|
|
35261
|
+
}
|
|
35262
|
+
async runTransaction(_evmTransactionData, solTransactionData, options) {
|
|
35263
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
35264
|
+
if (!solTransactionData) {
|
|
35265
|
+
throw new Error('Solana transaction data is required for mobile wallet');
|
|
35266
|
+
}
|
|
35267
|
+
const adapter = await this.ensureAdapter();
|
|
35268
|
+
if (!adapter.connected) {
|
|
35269
|
+
await this.login();
|
|
35270
|
+
}
|
|
35271
|
+
const rpcUrl = this.getRpcUrl(solTransactionData.network);
|
|
35272
|
+
const connection = new web3_js.Connection(rpcUrl, 'confirmed');
|
|
35273
|
+
const isSurfnet = rpcUrl === SURFNET_RPC_URL;
|
|
35274
|
+
try {
|
|
35275
|
+
const publicKey = adapter.publicKey;
|
|
35276
|
+
if (!publicKey) {
|
|
35277
|
+
throw new Error('No wallet connected');
|
|
35278
|
+
}
|
|
35279
|
+
const remainingAccounts = convertRemainingAccounts(solTransactionData.txArgs[0].remainingAccounts);
|
|
35280
|
+
let app_id = solTransactionData.appId;
|
|
35281
|
+
if (typeof window !== 'undefined' && window.CUSTOM_TAROBASE_APP_ID_HEADER) {
|
|
35282
|
+
app_id = window.CUSTOM_TAROBASE_APP_ID_HEADER;
|
|
35283
|
+
}
|
|
35284
|
+
if (!app_id) {
|
|
35285
|
+
throw new Error('App ID is required');
|
|
35286
|
+
}
|
|
35287
|
+
// Create wallet adapter interface for Anchor
|
|
35288
|
+
const walletAdapter = {
|
|
35289
|
+
publicKey,
|
|
35290
|
+
signTransaction: async (tx) => {
|
|
35291
|
+
return await adapter.signTransaction(tx);
|
|
35292
|
+
},
|
|
35293
|
+
signAllTransactions: async (txs) => {
|
|
35294
|
+
return await adapter.signAllTransactions(txs);
|
|
35295
|
+
}
|
|
35296
|
+
};
|
|
35297
|
+
const anchorProvider = new anchor__namespace.AnchorProvider(connection, walletAdapter, anchor__namespace.AnchorProvider.defaultOptions());
|
|
35298
|
+
const finalDeduped = [];
|
|
35299
|
+
for (const acc of remainingAccounts) {
|
|
35300
|
+
const existing = finalDeduped.find((d) => d.pubkey.equals(acc.pubkey));
|
|
35301
|
+
if (existing) {
|
|
35302
|
+
existing.isSigner = existing.isSigner || acc.isSigner;
|
|
35303
|
+
existing.isWritable = existing.isWritable || acc.isWritable;
|
|
35304
|
+
}
|
|
35305
|
+
else {
|
|
35306
|
+
finalDeduped.push(acc);
|
|
35307
|
+
}
|
|
35308
|
+
}
|
|
35309
|
+
const { tx } = await buildSetDocumentsTransaction(connection, solTransactionData.txArgs[0].idl, anchorProvider, publicKey, {
|
|
35310
|
+
app_id,
|
|
35311
|
+
documents: solTransactionData.txArgs[0].setDocumentData,
|
|
35312
|
+
delete_paths: solTransactionData.txArgs[0].deletePaths,
|
|
35313
|
+
txData: solTransactionData.txArgs[0].txData
|
|
35314
|
+
}, finalDeduped, solTransactionData.lutKey, solTransactionData.preInstructions, false);
|
|
35315
|
+
if ((options === null || options === void 0 ? void 0 : options.shouldSubmitTx) === false) {
|
|
35316
|
+
const signedTx = await walletAdapter.signTransaction(tx);
|
|
35317
|
+
return {
|
|
35318
|
+
signedTransaction: signedTx,
|
|
35319
|
+
blockNumber: 0,
|
|
35320
|
+
gasUsed: '0',
|
|
35321
|
+
data: ''
|
|
35322
|
+
};
|
|
35323
|
+
}
|
|
35324
|
+
// On surfnet, sign + submit manually
|
|
35325
|
+
if (isSurfnet) {
|
|
35326
|
+
const signedTx = await walletAdapter.signTransaction(tx);
|
|
35327
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
|
|
35328
|
+
const signature = await connection.sendRawTransaction(signedTx.serialize(), {
|
|
35329
|
+
preflightCommitment: 'confirmed'
|
|
35330
|
+
});
|
|
35331
|
+
const confirmation = await connection.confirmTransaction({
|
|
35332
|
+
signature,
|
|
35333
|
+
blockhash,
|
|
35334
|
+
lastValidBlockHeight,
|
|
35335
|
+
}, 'confirmed');
|
|
35336
|
+
if (confirmation.value.err) {
|
|
35337
|
+
throw new Error(`Transaction failed: ${confirmation.value.err.toString()}`);
|
|
35338
|
+
}
|
|
35339
|
+
const txInfo = await connection.getParsedTransaction(signature, {
|
|
35340
|
+
maxSupportedTransactionVersion: 0,
|
|
35341
|
+
commitment: 'confirmed'
|
|
35342
|
+
});
|
|
35343
|
+
return {
|
|
35344
|
+
transactionSignature: signature,
|
|
35345
|
+
blockNumber: (txInfo === null || txInfo === void 0 ? void 0 : txInfo.slot) || 0,
|
|
35346
|
+
gasUsed: ((_a = txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta) === null || _a === void 0 ? void 0 : _a.fee.toString()) || '0',
|
|
35347
|
+
data: txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta,
|
|
35348
|
+
};
|
|
35349
|
+
}
|
|
35350
|
+
// Use MWA's sendTransaction for mobile-optimized submission
|
|
35351
|
+
let signature;
|
|
35352
|
+
if (adapter.sendTransaction) {
|
|
35353
|
+
signature = await adapter.sendTransaction(tx, connection, {
|
|
35354
|
+
preflightCommitment: 'confirmed',
|
|
35355
|
+
});
|
|
35356
|
+
}
|
|
35357
|
+
else {
|
|
35358
|
+
const signedTx = await walletAdapter.signTransaction(tx);
|
|
35359
|
+
signature = await connection.sendRawTransaction(signedTx.serialize(), {
|
|
35360
|
+
preflightCommitment: 'confirmed'
|
|
35361
|
+
});
|
|
35362
|
+
}
|
|
35363
|
+
const txInfo = await confirmAndCheckTransaction(connection, signature);
|
|
35364
|
+
return {
|
|
35365
|
+
transactionSignature: signature,
|
|
35366
|
+
blockNumber: (txInfo === null || txInfo === void 0 ? void 0 : txInfo.slot) || 0,
|
|
35367
|
+
gasUsed: ((_b = txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta) === null || _b === void 0 ? void 0 : _b.fee.toString()) || '0',
|
|
35368
|
+
data: txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta,
|
|
35369
|
+
};
|
|
35370
|
+
}
|
|
35371
|
+
catch (error) {
|
|
35372
|
+
if (((_c = error === null || error === void 0 ? void 0 : error.message) === null || _c === void 0 ? void 0 : _c.includes('not connected')) || ((_d = error === null || error === void 0 ? void 0 : error.message) === null || _d === void 0 ? void 0 : _d.includes('not authorized'))) {
|
|
35373
|
+
await this.logout();
|
|
35374
|
+
throw new Error('Wallet connection lost. Please reconnect.');
|
|
35375
|
+
}
|
|
35376
|
+
const isUserRejection = (error === null || error === void 0 ? void 0 : error.code) === 4001 ||
|
|
35377
|
+
((_e = error === null || error === void 0 ? void 0 : error.message) === null || _e === void 0 ? void 0 : _e.toLowerCase().includes('user rejected')) ||
|
|
35378
|
+
((_f = error === null || error === void 0 ? void 0 : error.message) === null || _f === void 0 ? void 0 : _f.toLowerCase().includes('user denied')) ||
|
|
35379
|
+
((_g = error === null || error === void 0 ? void 0 : error.message) === null || _g === void 0 ? void 0 : _g.toLowerCase().includes('user cancelled')) ||
|
|
35380
|
+
((_h = error === null || error === void 0 ? void 0 : error.message) === null || _h === void 0 ? void 0 : _h.toLowerCase().includes('user canceled'));
|
|
35381
|
+
if (!isUserRejection) {
|
|
35382
|
+
console.error('[SolanaMobileWallet] Transaction failed:', error);
|
|
35383
|
+
}
|
|
35384
|
+
throw new Error(`Failed to execute transaction: ${error.message}`);
|
|
35385
|
+
}
|
|
35386
|
+
}
|
|
35387
|
+
async getNativeMethods() {
|
|
35388
|
+
return this.mwaAdapter;
|
|
35389
|
+
}
|
|
35390
|
+
/* ----------------------------------------------------------- *
|
|
35391
|
+
* Private Helpers
|
|
35392
|
+
* ----------------------------------------------------------- */
|
|
35393
|
+
getRpcUrl(network) {
|
|
35394
|
+
if (this.networkUrl) {
|
|
35395
|
+
return this.networkUrl;
|
|
35396
|
+
}
|
|
35397
|
+
if (network === 'solana_devnet') {
|
|
35398
|
+
return SOLANA_DEVNET_RPC_URL;
|
|
35399
|
+
}
|
|
35400
|
+
else if (network === 'solana_mainnet') {
|
|
35401
|
+
return SOLANA_MAINNET_RPC_URL;
|
|
35402
|
+
}
|
|
35403
|
+
else if (network === 'surfnet') {
|
|
35404
|
+
return SURFNET_RPC_URL;
|
|
35405
|
+
}
|
|
35406
|
+
return SOLANA_MAINNET_RPC_URL;
|
|
35407
|
+
}
|
|
35408
|
+
}
|
|
35409
|
+
SolanaMobileWalletProvider.instance = null;
|
|
35410
|
+
|
|
34900
35411
|
let currentAuthProvider = null;
|
|
34901
35412
|
let currentAuthMethod = null;
|
|
34902
35413
|
let initConfig = null;
|
|
@@ -34970,7 +35481,7 @@ const SOLANA_DEVNET_RPC_URL = "https://idelle-8nxsep-fast-devnet.helius-rpc.com"
|
|
|
34970
35481
|
const SOLANA_MAINNET_RPC_URL = "https://celestia-cegncv-fast-mainnet.helius-rpc.com";
|
|
34971
35482
|
const SURFNET_RPC_URL = "https://surfpool.fly.dev";
|
|
34972
35483
|
async function getAuthProvider(config) {
|
|
34973
|
-
var _a, _b, _c, _d;
|
|
35484
|
+
var _a, _b, _c, _d, _e, _f;
|
|
34974
35485
|
if (currentAuthProvider) {
|
|
34975
35486
|
return currentAuthProvider;
|
|
34976
35487
|
}
|
|
@@ -34985,7 +35496,7 @@ async function getAuthProvider(config) {
|
|
|
34985
35496
|
return currentAuthProvider;
|
|
34986
35497
|
}
|
|
34987
35498
|
// If the user previously logged in with a specific method, use that instead
|
|
34988
|
-
const validAuthMethods = ['privy', 'phantom', 'wallet', 'rainbowkit', 'coinbase-smart-wallet', 'onboard', 'none'];
|
|
35499
|
+
const validAuthMethods = ['privy', 'phantom', 'wallet', 'rainbowkit', 'coinbase-smart-wallet', 'onboard', 'mobile-wallet-adapter', 'none'];
|
|
34989
35500
|
const storedMethod = getStoredAuthMethod();
|
|
34990
35501
|
const authMethod = (storedMethod && validAuthMethods.includes(storedMethod))
|
|
34991
35502
|
? storedMethod
|
|
@@ -34994,7 +35505,25 @@ async function getAuthProvider(config) {
|
|
|
34994
35505
|
// Invalid stored value — clear it
|
|
34995
35506
|
setStoredAuthMethod(null);
|
|
34996
35507
|
}
|
|
34997
|
-
|
|
35508
|
+
// --- Register MWA as a wallet-standard wallet on mobile ---
|
|
35509
|
+
// On Android (TWA via Bubblewrap, Chrome, or mobile browser), register the
|
|
35510
|
+
// Mobile Wallet Adapter so it appears in wallet discovery (e.g. Phantom's
|
|
35511
|
+
// useDiscoveredWallets, or any wallet-standard consumer). This makes Seed
|
|
35512
|
+
// Vault, Solflare, and other MWA wallets show up alongside injected wallets
|
|
35513
|
+
// in the existing Phantom/Privy modals — without overriding the configured
|
|
35514
|
+
// authMethod. Email login, deeplinks, and all other flows stay intact.
|
|
35515
|
+
//
|
|
35516
|
+
// Only authMethod: 'mobile-wallet-adapter' (explicit opt-in) bypasses
|
|
35517
|
+
// Phantom/Privy entirely and uses MWA as the sole provider.
|
|
35518
|
+
if (isMobileWalletAvailable()) {
|
|
35519
|
+
registerMobileWalletAdapter({
|
|
35520
|
+
appIdentity: (_b = (_a = config.mobileWalletConfig) === null || _a === void 0 ? void 0 : _a.appIdentity) !== null && _b !== void 0 ? _b : {
|
|
35521
|
+
name: config.name || undefined,
|
|
35522
|
+
uri: typeof window !== 'undefined' ? window.location.origin : undefined,
|
|
35523
|
+
},
|
|
35524
|
+
}).catch(() => { });
|
|
35525
|
+
}
|
|
35526
|
+
const rpcUrl = (_c = config.rpcUrl) !== null && _c !== void 0 ? _c : null;
|
|
34998
35527
|
currentAuthMethod = authMethod;
|
|
34999
35528
|
switch (authMethod) {
|
|
35000
35529
|
case "wallet":
|
|
@@ -35004,15 +35533,18 @@ async function getAuthProvider(config) {
|
|
|
35004
35533
|
console.warn("Rainbow Kit auth is not yet supported.");
|
|
35005
35534
|
break;
|
|
35006
35535
|
case "privy":
|
|
35007
|
-
currentAuthProvider = new PrivyWalletProvider((
|
|
35536
|
+
currentAuthProvider = new PrivyWalletProvider((_d = config.name) !== null && _d !== void 0 ? _d : null, (_e = config.logoUrl) !== null && _e !== void 0 ? _e : null, config.privyConfig, rpcUrl);
|
|
35008
35537
|
break;
|
|
35009
35538
|
case "phantom":
|
|
35010
35539
|
currentAuthProvider = new PhantomWalletProvider(rpcUrl, config.phantomConfig);
|
|
35011
|
-
if ((
|
|
35540
|
+
if ((_f = config.phantomConfig) === null || _f === void 0 ? void 0 : _f.enablePrivyFallback) {
|
|
35012
35541
|
currentAuthProvider.onSwitchToPrivy =
|
|
35013
35542
|
() => hotSwapToPrivyProvider(config);
|
|
35014
35543
|
}
|
|
35015
35544
|
break;
|
|
35545
|
+
case "mobile-wallet-adapter":
|
|
35546
|
+
currentAuthProvider = new SolanaMobileWalletProvider(rpcUrl, config.mobileWalletConfig);
|
|
35547
|
+
break;
|
|
35016
35548
|
case "onboard":
|
|
35017
35549
|
console.warn("Onboard auth is not yet supported.");
|
|
35018
35550
|
break;
|
|
@@ -35235,6 +35767,7 @@ exports.OffchainAuthProvider = OffchainAuthProvider;
|
|
|
35235
35767
|
exports.PhantomWalletProvider = PhantomWalletProvider;
|
|
35236
35768
|
exports.PrivyWalletProvider = PrivyWalletProvider;
|
|
35237
35769
|
exports.ServerSessionManager = ServerSessionManager;
|
|
35770
|
+
exports.SolanaMobileWalletProvider = SolanaMobileWalletProvider;
|
|
35238
35771
|
exports.WebSessionManager = WebSessionManager;
|
|
35239
35772
|
exports.aggregate = aggregate;
|
|
35240
35773
|
exports.bs58 = bs58;
|
|
@@ -35257,12 +35790,14 @@ exports.getCurrentUser = getCurrentUser;
|
|
|
35257
35790
|
exports.getFiles = getFiles;
|
|
35258
35791
|
exports.getIdToken = getIdToken;
|
|
35259
35792
|
exports.init = init;
|
|
35793
|
+
exports.isMobileWalletAvailable = isMobileWalletAvailable;
|
|
35260
35794
|
exports.login = login;
|
|
35261
35795
|
exports.logout = logout;
|
|
35262
35796
|
exports.onAuthLoadingChanged = onAuthLoadingChanged;
|
|
35263
35797
|
exports.onAuthStateChanged = onAuthStateChanged;
|
|
35264
35798
|
exports.reconnectWithNewAuth = reconnectWithNewAuth;
|
|
35265
35799
|
exports.refreshSession = refreshSession;
|
|
35800
|
+
exports.registerMobileWalletAdapter = registerMobileWalletAdapter;
|
|
35266
35801
|
exports.runExpression = runExpression;
|
|
35267
35802
|
exports.runExpressionMany = runExpressionMany;
|
|
35268
35803
|
exports.runQuery = runQuery;
|
|
@@ -35276,4 +35811,4 @@ exports.signSessionCreateMessage = signSessionCreateMessage;
|
|
|
35276
35811
|
exports.signTransaction = signTransaction;
|
|
35277
35812
|
exports.subscribe = subscribe;
|
|
35278
35813
|
exports.useAuth = useAuth;
|
|
35279
|
-
//# sourceMappingURL=index-
|
|
35814
|
+
//# sourceMappingURL=index-C4TkISTV.js.map
|