project-serum / sol-wallet-adapter

Other
185 stars 93 forks source link

support generic injected interface by passing provider object to the constructor #11

Closed Zergity closed 3 years ago

Zergity commented 3 years ago

This minimal change allows sol-wallet-adapter to interact with any browser extension by passing non URL value to the constructor.

yuzhiyou1990 commented 3 years ago
/* 
// project-serum/serum-dex-ui
// https://github.com/project-serum/serum-dex-ui/blob/master/src/utils/wallet.tsx

export const WALLET_PROVIDERS = [
  { name: 'sollet.io', url: 'https://www.sollet.io' },
  { name: 'mathwallet', url: 'https://www.mathwallet.org' }
];
*/
// provider = {name:"mathwallet or ezdefi",url:"xxxxxxx"} or provider = "https://www.sollet.io"
constructor(provider, network) {
    super();
    this._providerUrl = isObject(provider) ? new URL(provider.url) : new URL(provider);
    this._providerUrl.hash = new URLSearchParams({
      origin: window.location.origin,
      network,
    }).toString();
    this._injectedProvider = injectedProvider(provider);
    this._publicKey = null;
    this._autoApprove = false;
    this._popup = null;
    this._handlerAdded = false;
    this._nextRequestId = 1;
    this._responsePromises = new Map();
  }

function injectedProvider(provider) {
  if (isObject(provider) && isObject(window.solana) && isObject(window.solana[provider.name]) && isFunction(window.solana[provider.name].postMessage)) {
     return window.solana[provider.name];
  }
  return null;
}

function isObject(a) {
  return typeof a === 'object' && a !== null;
}

function isFunction(a) {
  return typeof a === 'function';
}
Zergity commented 3 years ago
  • When there is no injected object, the official website can still be opened

IIUC, you want the adapter to show the installation/website when the injected object is not installed. In my mind, that should be handled in the dapp code. But if we want to do it in the adapter code, may I suggest this constructor. (We also don't want to lock the injected interface, i.e. let each wallet inject they way they want.)

  constructor(providerUrl, network, injectedProvider) {
    super();
    if (injectedProvider && isInjectedProvider(injectedProvider)) {
      this._injectedProvider = injectedProvider
    }
    this._providerUrl = new URL(providerUrl);
    this._providerUrl.hash = new URLSearchParams({
      origin: window.location.origin,
      network,
    }).toString();
    ...
  }

The wallet can be initialized by the following ways or any logic it's desired:

new Wallet('https://solet.io', network);
new Wallet('https://mathwallet.org', network, (window.solana||{}).mathwallet);
new Wallet('https://ezdefi.com', network, Object.values(window.solana||{}).find(w=>w.name=='ezdefi'));
armaniferrante commented 3 years ago

Closing this in favor of #15, which builds on the PR here.