@soundsright/connector
Version:
soundsright wallet connector
238 lines (237 loc) • 10.3 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WalletConnectConnection = exports.RPC_CONFIGS = void 0;
const ethers_1 = require("ethers");
const config_1 = require("@soundsright/config");
const types_1 = require("../types");
exports.RPC_CONFIGS = Object.keys(config_1.NETWORKS).reduce((pv, v) => {
pv[v] = config_1.NETWORKS[v].rpcUrls[0]; // eslint-disable-line
return pv;
}, {});
class WalletConnectConnection extends types_1.Connection {
constructor() {
super();
this.eagerConnection = null;
this.ethereum = null;
this.registDefaultUriHandler();
}
static getInstance() {
if (!WalletConnectConnection._instance) {
WalletConnectConnection._instance = new this();
}
return WalletConnectConnection._instance;
}
_initialize() {
return __awaiter(this, void 0, void 0, function* () {
const EthereumProvider = (yield Promise.resolve().then(() => __importStar(require('@walletconnect/ethereum-provider')))).default;
const ethereum = new EthereumProvider({
qrcode: false,
chainId: +Object.keys(exports.RPC_CONFIGS)[0],
rpc: exports.RPC_CONFIGS,
});
this.state.provider = new ethers_1.ethers.providers.Web3Provider(ethereum);
ethereum.on('connect', () => {
this.state.provider = new ethers_1.ethers.providers.Web3Provider(ethereum);
this.state.signer = this.state.provider.getSigner();
this.state.account = ethereum.accounts[0];
this.state.chainId = ethereum.chainId;
this.state.connected = true;
this.emitChange('connect');
});
ethereum.on('disconnect', (error) => {
this.state.account = undefined;
this.state.chainId = undefined;
this.state.signer = undefined;
this.state.connected = undefined;
this.emitChange('disconnect', error);
});
ethereum.on('accountsChanged', (accounts) => {
this.state.account = accounts[0];
this.state.signer = this.state.provider.getSigner();
this.emitChange('accountsChanged');
});
ethereum.on('chainChanged', (chainIdStr) => {
this.state.provider = new ethers_1.ethers.providers.Web3Provider(ethereum);
this.state.signer = this.state.provider.getSigner();
this.state.chainId = Number.parseInt(chainIdStr);
this.emitChange('chainChanged');
});
// 特殊事件1 - 该事件每次disconnect
ethereum.connector.on('display_uri', (err, payload) => {
this.emit('uriAvailable', payload.params[0]);
});
// 特殊事件2:
// @ts-ignore 修正手机扫码时取消连接,无法自动关闭弹窗的bug
ethereum.signer.connection.wc.on('disconnect', () => {
this.emit('close');
this.disconnect(false);
});
this.ethereum = ethereum;
return this.ethereum;
});
}
initialize() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.eagerConnection) {
this.eagerConnection = this._initialize();
}
return this.eagerConnection;
});
}
connect() {
return __awaiter(this, void 0, void 0, function* () {
yield this.initialize();
const { ethereum } = this;
const accounts = yield ethereum.request({ method: 'eth_requestAccounts' });
// .catch((err: Error) => {
// if (err.message === 'User closed modal') {
// this.disconnect();
// }
// throw err;
// });
this.state.account = accounts[0];
if (ethereum.setHttpProvider) {
ethereum.http = ethereum.setHttpProvider(ethereum.chainId);
} // 非标准方法,处理一下内部在链不一致时的bug
this.state.provider = new ethers_1.ethers.providers.Web3Provider(ethereum);
this.state.signer = this.state.provider.getSigner();
this.state.chainId = ethereum.chainId;
this.state.connected = true;
this.emitChange('connect');
return this.state;
});
}
switchChain(chainId) {
return __awaiter(this, void 0, void 0, function* () {
if (chainId === this.state.chainId)
return;
const { ethereum } = this;
const chainIdStr = `0x${Number(chainId).toString(16)}`;
try {
yield ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: chainIdStr }],
});
}
catch (e) {
const network = config_1.NETWORKS[chainId];
const message = e.message || e;
if (message.indexOf('wallet_addEthereumChain') < 0) {
throw new Error(e);
}
yield ethereum.request({
method: 'wallet_addEthereumChain',
params: [{
chainId: chainIdStr,
chainName: network.chainName,
rpcUrls: network.rpcUrls,
nativeCurrency: network.nativeCurrency,
blockExplorerUrls: network.blockExplorerUrls,
}],
});
}
yield new Promise((resolve) => {
const timer = setTimeout(() => {
this.state.provider = new ethers_1.ethers.providers.Web3Provider(ethereum);
this.state.signer = this.state.provider.getSigner();
this.state.chainId = chainId;
resolve(undefined);
}, 2000);
this.once('chainChanged', () => {
if (timer)
clearTimeout(timer);
resolve(undefined);
});
});
});
}
addToken(options) {
return __awaiter(this, void 0, void 0, function* () {
const { ethereum } = this;
yield ethereum.request({
method: 'wallet_watchAsset',
params: {
type: 'ERC20',
options,
},
});
});
}
disconnect(emit = true) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
this.state.account = undefined;
this.state.chainId = undefined;
this.state.signer = undefined;
this.state.connected = undefined;
yield ((_a = this.ethereum) === null || _a === void 0 ? void 0 : _a.disconnect());
this.eagerConnection = null;
this.ethereum = null;
if (emit) {
this.emitChange('disconnect');
}
});
}
registUriHandler(handler) {
if (!this.uriHandler) {
let close;
this.on('uriAvailable', (uri) => {
close = this.uriHandler(uri, () => this.disconnect(false));
});
this.on('connect', () => {
if (close)
close();
});
this.on('close', () => {
if (close)
close();
});
}
this.uriHandler = handler;
}
registDefaultUriHandler() {
let QRCodeModal = null;
this.registUriHandler((uri, disconnect) => {
(() => __awaiter(this, void 0, void 0, function* () {
if (!QRCodeModal) {
QRCodeModal = (yield Promise.resolve().then(() => __importStar(require('@walletconnect/qrcode-modal')))).default;
}
QRCodeModal.open(uri, disconnect);
}))();
return () => QRCodeModal.close();
});
}
}
exports.WalletConnectConnection = WalletConnectConnection;