sui-svelte-wallet-kit
Version:
Svelte 5 wallet kit for Sui: connect wallets, manage accounts, SuiNS, balance, sign transactions/messages
178 lines (177 loc) • 6.38 kB
JavaScript
import { AllDefaultWallets, WalletRadar } from '@suiet/wallet-sdk';
import { getWallets } from '@wallet-standard/core';
// Browser guard
const isBrowser = typeof window !== 'undefined';
// Debug toggle
export const isDiscoveryDebugEnabled = () => {
if (!isBrowser)
return false;
try {
return window.localStorage.getItem('sui-wallet-kit-debug') === '1';
}
catch {
return false;
}
};
// Adapter detection
export const uniqueAdaptersByName = (adapters) => {
const map = new Map();
for (const a of adapters || []) {
if (!a || !a.name)
continue;
if (!map.has(a.name))
map.set(a.name, a);
}
return Array.from(map.values());
};
export const detectWalletAdapters = () => {
if (!isBrowser)
return [];
const walletRadar = new WalletRadar();
walletRadar.activate();
const radarAdapters = walletRadar.getDetectedWalletAdapters();
let registryWallets = [];
try {
const registry = getWallets?.();
if (registry && typeof registry.get === 'function') {
registryWallets = registry.get() || [];
}
}
catch { }
walletRadar.deactivate();
return uniqueAdaptersByName([...(radarAdapters || []), ...Array.from(registryWallets || [])]);
};
// Wallet list construction
const normalizeWalletName = (name) => (name || '')
.toLowerCase()
.replace(/wallet$/g, '')
.replace(/[^a-z0-9]/g, '');
const applyWalletConfig = (wallets, config) => {
const { customNames = {}, ordering = [] } = config;
const walletsWithCustomNames = wallets.map((wallet) => {
const customName = customNames[wallet.name];
return customName ? { ...wallet, displayName: customName, originalName: wallet.name } : wallet;
});
const result = ordering.length > 0
? walletsWithCustomNames.sort((a, b) => {
const aName = a.originalName || a.name;
const bName = b.originalName || b.name;
const aIndex = ordering.indexOf(aName);
const bIndex = ordering.indexOf(bName);
if (aIndex !== -1 && bIndex !== -1) {
return aIndex - bIndex;
}
if (aIndex !== -1)
return -1;
if (bIndex !== -1)
return 1;
return aName.localeCompare(bName);
})
: walletsWithCustomNames;
return result;
};
export const getAvailableWallets = (defaultWallets, detectedAdapters, config = {}) => {
const adapters = Array.isArray(detectedAdapters) ? detectedAdapters : detectWalletAdapters();
const list = defaultWallets.map((item) => {
const normalizedItem = normalizeWalletName(item.name);
const foundAdapter = adapters.find((walletAdapter) => {
const normalizedAdapter = normalizeWalletName(walletAdapter.name);
return (normalizedItem.includes(normalizedAdapter) || normalizedAdapter.includes(normalizedItem));
});
return {
...item,
name: item.name,
iconUrl: item.iconUrl,
adapter: foundAdapter ? foundAdapter : undefined,
installed: !!foundAdapter
};
});
const defaultNormalizedNames = defaultWallets.map((w) => normalizeWalletName(w.name));
const extraAdapters = adapters.filter((a) => {
const na = normalizeWalletName(a.name);
return !defaultNormalizedNames.some((dn) => dn.includes(na) || na.includes(dn));
});
const extraWalletEntries = extraAdapters.map((a) => ({
name: a.name,
originalName: a.name,
displayName: a.name,
iconUrl: typeof a.icon === 'string' ? a.icon : undefined,
adapter: a,
installed: true
}));
return applyWalletConfig([...list, ...extraWalletEntries], config);
};
const _discoverySubscribers = new Set();
export const subscribeWalletDiscovery = (callback) => {
if (typeof callback !== 'function')
return () => { };
_discoverySubscribers.add(callback);
return () => {
_discoverySubscribers.delete(callback);
};
};
export const notifyDiscoverySubscribers = (adapters, wallets) => {
try {
for (const cb of _discoverySubscribers) {
try {
cb(adapters, wallets);
}
catch { }
}
}
catch { }
};
export const setModuleWalletDiscovery = (adapters, wallets, targetAdapters, targetWallets) => {
const nextAdapters = Array.isArray(adapters) ? adapters : [];
const nextWallets = Array.isArray(wallets) ? wallets : [];
targetAdapters.length = 0;
targetAdapters.push(...nextAdapters);
targetWallets.length = 0;
targetWallets.push(...nextWallets);
notifyDiscoverySubscribers(targetAdapters, targetWallets);
};
let _lastDiscoveryLogKey = '';
let _lastAvailableLogKey = '';
let _discoveryAttempt = 0;
export const refreshDiscoverySnapshot = (attemptLabel, walletConfig) => {
const snapshot = uniqueAdaptersByName(detectWalletAdapters());
try {
const adapterNames = snapshot
.map((a) => a?.name)
.filter(Boolean)
.sort();
const key = adapterNames.join('|');
if (key !== _lastDiscoveryLogKey) {
_lastDiscoveryLogKey = key;
if (isDiscoveryDebugEnabled()) {
const ts = new Date().toISOString();
console.log(`[SuiModule] [${ts}] [attempt:${attemptLabel ?? '-'}] Detected adapters:`, adapterNames);
}
}
}
catch { }
const wallets = getAvailableWallets(AllDefaultWallets, snapshot, walletConfig);
try {
const walletNames = wallets
.map((w) => w?.name)
.filter(Boolean)
.sort();
const wkey = walletNames.join('|');
if (wkey !== _lastAvailableLogKey) {
_lastAvailableLogKey = wkey;
if (isDiscoveryDebugEnabled()) {
const ts = new Date().toISOString();
console.log(`[SuiModule] [${ts}] [attempt:${attemptLabel ?? '-'}] Available wallets:`, walletNames);
}
}
}
catch { }
return { adapters: snapshot, wallets };
};
export const getDiscoveryAttempt = () => {
return _discoveryAttempt;
};
export const incrementDiscoveryAttempt = () => {
_discoveryAttempt += 1;
return _discoveryAttempt;
};