mirror of
https://github.com/luxfi/eth-walletconnect-keyring.git
synced 2026-10-30 16:58:01 +00:00
839 lines
24 KiB
TypeScript
839 lines
24 KiB
TypeScript
// https://github.com/MetaMask/eth-simple-keyring#the-keyring-class-protocol
|
|
import WalletConnect from '@luxwallet/wc-client';
|
|
import { IClientMeta } from '@luxwallet/wc-types';
|
|
import {
|
|
TypedTransaction,
|
|
JsonTx,
|
|
Transaction,
|
|
FeeMarketEIP1559Transaction
|
|
} from '@ethereumjs/tx';
|
|
import {
|
|
bufferToHex,
|
|
convertToBigint,
|
|
getChainId,
|
|
isBrowser,
|
|
wait
|
|
} from './utils';
|
|
import { SDK } from './sdk';
|
|
import { sanitizeHex } from './helper';
|
|
import {
|
|
WALLETCONNECT_STATUS_MAP,
|
|
WALLETCONNECT_SESSION_STATUS_MAP,
|
|
COMMON_WALLETCONNECT,
|
|
buildInWallets,
|
|
BuildInWalletPeerName,
|
|
IGNORE_CHECK_WALLET,
|
|
Account,
|
|
ConstructorOptions
|
|
} from './type';
|
|
|
|
export const DEFAULT_BRIDGE = 'https://derelay.lux.io';
|
|
|
|
type ValueOf<T> = T[keyof T];
|
|
|
|
type ConnectPayload = {
|
|
params: {
|
|
accounts: string[];
|
|
peerMeta: IClientMeta;
|
|
chainId: number;
|
|
}[];
|
|
};
|
|
|
|
interface Connector {
|
|
connector: WalletConnect;
|
|
status: ValueOf<typeof WALLETCONNECT_STATUS_MAP>;
|
|
networkDelay: number;
|
|
brandName: string;
|
|
chainId?: number;
|
|
sessionStatus?: keyof typeof WALLETCONNECT_SESSION_STATUS_MAP;
|
|
preSessionStatus?: keyof typeof WALLETCONNECT_SESSION_STATUS_MAP;
|
|
peerMeta: IClientMeta;
|
|
silent?: boolean;
|
|
}
|
|
|
|
export class V1SDK extends SDK {
|
|
accounts: Account[] = [];
|
|
accountToAdd: Account | null = null;
|
|
resolvePromise: null | ((value: any) => void) = null;
|
|
rejectPromise: null | ((value: any) => void) = null;
|
|
onAfterConnect: null | ((err?: any, payload?: any) => void) = null;
|
|
onDisconnect: null | ((err: any, payload: any) => void) = null;
|
|
currentConnectStatus: number = WALLETCONNECT_STATUS_MAP.PENDING;
|
|
maxDuration = 1800000; // 30 mins hour by default
|
|
clientMeta: IClientMeta | null = null;
|
|
currentConnector: Connector | null = null;
|
|
connectors: Record<string, Connector> = {};
|
|
currentConnectParams: any = null;
|
|
|
|
version = 1;
|
|
|
|
constructor(opts: ConstructorOptions) {
|
|
super();
|
|
this.accounts = opts.accounts || [];
|
|
this.clientMeta = opts.clientMeta;
|
|
}
|
|
|
|
initConnector = async (brandName: string) => {
|
|
let address: string | null = null;
|
|
const connector = await this.createConnector(brandName);
|
|
|
|
this.onAfterConnect = (error, payload: ConnectPayload) => {
|
|
const [account] = payload.params[0].accounts;
|
|
address = account;
|
|
const lowerAddress = address!.toLowerCase();
|
|
const conn = this.connectors[`${brandName}-${lowerAddress}`];
|
|
|
|
this.currentConnector = this.connectors[`${brandName}-${lowerAddress}`] =
|
|
{
|
|
...conn,
|
|
status: WALLETCONNECT_STATUS_MAP.CONNECTED,
|
|
chainId: payload.params[0].chainId,
|
|
brandName,
|
|
sessionStatus: 'CONNECTED'
|
|
} as Connector;
|
|
|
|
this.updateCurrentStatus(WALLETCONNECT_STATUS_MAP.CONNECTED, null, {
|
|
...payload.params[0],
|
|
account
|
|
});
|
|
};
|
|
this.onDisconnect = (error, payload) => {
|
|
if (address) {
|
|
const connector =
|
|
this.connectors[`${brandName}-${address.toLowerCase()}`];
|
|
if (connector) {
|
|
this._closeConnector(connector.connector, address, brandName);
|
|
}
|
|
}
|
|
this.updateCurrentStatus(
|
|
WALLETCONNECT_STATUS_MAP.FAILD,
|
|
null,
|
|
error || payload.params[0]
|
|
);
|
|
};
|
|
|
|
this.emit('inited', connector.uri);
|
|
|
|
return connector;
|
|
};
|
|
|
|
getConnectorInfoByClientId(clientId: string) {
|
|
const connectorKey = Object.keys(this.connectors).find(
|
|
(key) => this.connectors[key]?.connector?.clientId === clientId
|
|
);
|
|
if (!connectorKey) {
|
|
return;
|
|
}
|
|
|
|
const [brandName, address] = connectorKey.split('-');
|
|
const account = this.accounts.find(
|
|
(acc) =>
|
|
acc.address.toLowerCase() === address.toLowerCase() &&
|
|
acc.brandName === brandName
|
|
)!;
|
|
|
|
return {
|
|
brandName,
|
|
address,
|
|
connectorKey,
|
|
account
|
|
};
|
|
}
|
|
|
|
getBuildInBrandName(
|
|
brandName: string,
|
|
realBrandName?: string,
|
|
patchCheckWalletConnect?: boolean
|
|
) {
|
|
if (patchCheckWalletConnect) {
|
|
// is desktop
|
|
if (brandName === 'WalletConnect') return brandName;
|
|
}
|
|
|
|
if (!COMMON_WALLETCONNECT.includes(brandName)) {
|
|
return brandName;
|
|
}
|
|
|
|
const lowerName = realBrandName?.toLowerCase();
|
|
if (!lowerName) return brandName;
|
|
let buildIn = buildInWallets.find((item) => {
|
|
const lowerItem = item.toLowerCase();
|
|
return lowerItem.includes(lowerName) || lowerName.includes(lowerItem);
|
|
});
|
|
|
|
if (lowerName.includes('tokenpocket')) {
|
|
return 'TP';
|
|
}
|
|
if (lowerName.includes('trust wallet')) {
|
|
return 'TRUSTWALLET';
|
|
}
|
|
|
|
return buildIn || brandName;
|
|
}
|
|
|
|
createConnector = async (brandName: string, curAccount?: Account) => {
|
|
if (isBrowser() && typeof localStorage !== 'undefined') {
|
|
// always clear walletconnect cache
|
|
localStorage.removeItem('walletconnect');
|
|
}
|
|
const connector = new WalletConnect({
|
|
bridge: DEFAULT_BRIDGE,
|
|
clientMeta: this.clientMeta!
|
|
});
|
|
connector.on('connect', (error, payload) => {
|
|
if (payload?.params[0]?.accounts) {
|
|
const [account] = payload.params[0].accounts;
|
|
const buildInBrand = this.getBuildInBrandName(
|
|
brandName,
|
|
payload.params[0].peerMeta?.name,
|
|
// if is old account and is desktop, should ignore check
|
|
!!curAccount
|
|
);
|
|
const conn = (this.connectors[
|
|
`${buildInBrand}-${account.toLowerCase()}`
|
|
] = {
|
|
connector,
|
|
status: connector.connected
|
|
? WALLETCONNECT_STATUS_MAP.CONNECTED
|
|
: WALLETCONNECT_STATUS_MAP.PENDING,
|
|
chainId: payload?.params[0]?.chainId,
|
|
brandName: buildInBrand,
|
|
sessionStatus: 'CONNECTED',
|
|
peerMeta: payload?.params[0]?.peerMeta
|
|
} as Connector);
|
|
|
|
setTimeout(() => {
|
|
this._closeConnector(connector, account, buildInBrand);
|
|
}, this.maxDuration);
|
|
|
|
// check brandName
|
|
if (
|
|
!COMMON_WALLETCONNECT.includes(buildInBrand) &&
|
|
!this._checkBrandName(buildInBrand, payload)
|
|
) {
|
|
conn.sessionStatus = 'BRAND_NAME_ERROR';
|
|
this.updateSessionStatus('BRAND_NAME_ERROR', {
|
|
address: curAccount?.address || account,
|
|
brandName: curAccount?.brandName || buildInBrand
|
|
});
|
|
this._close(account, buildInBrand, true);
|
|
return;
|
|
}
|
|
|
|
if (curAccount) {
|
|
if (
|
|
account.toLowerCase() !== curAccount?.address.toLowerCase() ||
|
|
buildInBrand !== curAccount?.brandName
|
|
) {
|
|
conn.sessionStatus = 'ACCOUNT_ERROR';
|
|
this.updateSessionStatus('ACCOUNT_ERROR', curAccount);
|
|
this._close(account, buildInBrand, true);
|
|
return;
|
|
}
|
|
}
|
|
|
|
this.updateSessionStatus('CONNECTED', {
|
|
address: account,
|
|
brandName: buildInBrand,
|
|
realBrandName: conn.peerMeta?.name
|
|
});
|
|
this.emit('sessionAccountChange', {
|
|
address: account,
|
|
brandName: buildInBrand,
|
|
chainId: conn.chainId
|
|
});
|
|
|
|
this.currentConnector = conn;
|
|
|
|
this.updateCurrentStatus(WALLETCONNECT_STATUS_MAP.CONNECTED, null, {
|
|
...payload.params[0],
|
|
account
|
|
});
|
|
}
|
|
|
|
this.currentConnectParams = [error, payload];
|
|
});
|
|
|
|
connector.on(
|
|
'session_update',
|
|
(
|
|
error,
|
|
payload: {
|
|
event: string;
|
|
params: {
|
|
accounts: string[];
|
|
chainId: number;
|
|
}[];
|
|
}
|
|
) => {
|
|
const data = this.getConnectorInfoByClientId(connector.clientId);
|
|
if (!data) return;
|
|
const { connectorKey, address: _address, brandName: _brandName } = data;
|
|
const _chainId = this.connectors[connectorKey].chainId;
|
|
const updateAddress = payload.params[0].accounts[0];
|
|
const updateChain = payload.params[0].chainId;
|
|
|
|
if (updateAddress.toLowerCase() !== _address.toLowerCase()) {
|
|
this.connectors[connectorKey].sessionStatus = 'ACCOUNT_ERROR';
|
|
this.updateSessionStatus('ACCOUNT_ERROR', {
|
|
address: _address,
|
|
brandName: _brandName
|
|
});
|
|
} else {
|
|
this.connectors[connectorKey].sessionStatus = 'CONNECTED';
|
|
this.updateSessionStatus('CONNECTED', {
|
|
address: _address,
|
|
brandName: _brandName
|
|
});
|
|
}
|
|
|
|
this.emit('sessionAccountChange', {
|
|
address: _address,
|
|
brandName: _brandName,
|
|
chainId: updateChain
|
|
});
|
|
this.connectors[connectorKey].chainId = updateChain;
|
|
}
|
|
);
|
|
|
|
connector.on('ack', (error, payload) => {
|
|
const data = this.getConnectorInfoByClientId(connector.clientId);
|
|
if (data) {
|
|
// todo
|
|
const conn = this.connectors[data.connectorKey];
|
|
if (conn.status === WALLETCONNECT_STATUS_MAP.CONNECTED) {
|
|
this.updateCurrentStatus(
|
|
WALLETCONNECT_STATUS_MAP.WAITING,
|
|
data.account
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
|
|
this.updateSessionStatus('RECEIVED');
|
|
});
|
|
|
|
connector.on('session_resumed', (error, payload) => {
|
|
const data = this.getConnectorInfoByClientId(connector.clientId);
|
|
if (!data) return;
|
|
const conn = this.connectors[data.connectorKey];
|
|
conn.sessionStatus = conn.preSessionStatus ?? 'CONNECTED';
|
|
this.updateSessionStatus(conn.sessionStatus, {
|
|
address: data.address,
|
|
brandName: data.brandName
|
|
});
|
|
});
|
|
|
|
connector.on('session_suspended', (error, payload) => {
|
|
const data = this.getConnectorInfoByClientId(connector.clientId);
|
|
if (!data) {
|
|
this.updateSessionStatus('REJECTED');
|
|
return;
|
|
}
|
|
const conn = this.connectors[data.connectorKey];
|
|
if (conn.sessionStatus !== 'DISCONNECTED') {
|
|
conn.preSessionStatus = conn.sessionStatus;
|
|
}
|
|
conn.sessionStatus = 'DISCONNECTED';
|
|
this.updateSessionStatus('DISCONNECTED', {
|
|
address: data.address,
|
|
brandName: data.brandName
|
|
});
|
|
});
|
|
|
|
connector.on('disconnect', (error, payload) => {
|
|
if (payload.params[0]?.message.toLowerCase().includes('rejected')) {
|
|
this.updateSessionStatus('REJECTED');
|
|
return;
|
|
}
|
|
const data = this.getConnectorInfoByClientId(connector.clientId);
|
|
if (!data) return;
|
|
const { silent } = this.connectors[data.connectorKey];
|
|
if (!silent) {
|
|
this.connectors[data.connectorKey].sessionStatus = 'DISCONNECTED';
|
|
this.updateSessionStatus('DISCONNECTED', {
|
|
address: data.address,
|
|
brandName: data.brandName
|
|
});
|
|
}
|
|
this.onDisconnect && this.onDisconnect(error, payload);
|
|
});
|
|
|
|
connector.on('transport_error', (error, payload) => {
|
|
this.emit('transport_error', payload);
|
|
const data = this.getConnectorInfoByClientId(connector.clientId);
|
|
|
|
if (data) {
|
|
this._closeConnector(connector, data.address, data.brandName);
|
|
}
|
|
});
|
|
|
|
connector.on('transport_pong', (error, { params: [{ delay }] }) => {
|
|
const data = this.getConnectorInfoByClientId(connector.clientId);
|
|
if (!data) return;
|
|
this.connectors[data.connectorKey].networkDelay = delay;
|
|
this.emit('sessionNetworkDelay', {
|
|
address: data.address,
|
|
brandName: data.brandName,
|
|
delay
|
|
});
|
|
});
|
|
|
|
await connector.createSession();
|
|
|
|
return connector;
|
|
};
|
|
|
|
closeConnector: SDK['closeConnector'] = async (account: Account, silent) => {
|
|
const { brandName, address } = account;
|
|
const connector = this.connectors[`${brandName}-${address.toLowerCase()}`];
|
|
this._closeConnector(connector.connector, address, brandName, silent);
|
|
};
|
|
|
|
private _closeConnector = async (
|
|
connector: WalletConnect,
|
|
address: string,
|
|
brandName: string,
|
|
// don't broadcast close messages
|
|
silent?: boolean
|
|
) => {
|
|
try {
|
|
this.connectors[`${brandName}-${address.toLowerCase()}`].silent = silent;
|
|
connector?.transportClose();
|
|
if (connector?.connected) {
|
|
await connector.killSession();
|
|
}
|
|
} catch (e) {
|
|
// NOTHING
|
|
}
|
|
if (address) {
|
|
delete this.connectors[`${brandName}-${address.toLowerCase()}`];
|
|
}
|
|
};
|
|
|
|
init = async (address: string, brandName: string) => {
|
|
if (isBrowser() && typeof localStorage !== 'undefined') {
|
|
// always clear walletconnect cache
|
|
localStorage.removeItem('walletconnect');
|
|
}
|
|
|
|
const account = this.accounts.find(
|
|
(acc) =>
|
|
acc.address.toLowerCase() === address.toLowerCase() &&
|
|
acc.brandName === brandName
|
|
);
|
|
let connector;
|
|
if (account) {
|
|
const lowerAddress = account?.address.toLowerCase();
|
|
connector = this.connectors[`${brandName}-${lowerAddress}`];
|
|
if (!connector?.connector?.connected) {
|
|
const newConnector = await this.createConnector(brandName, account);
|
|
connector = {
|
|
...this.connectors[`${brandName}-${lowerAddress}`],
|
|
connector: newConnector,
|
|
status: WALLETCONNECT_STATUS_MAP.PENDING
|
|
};
|
|
}
|
|
}
|
|
|
|
// make sure the connector is the latest one before trigger onAfterConnect
|
|
this.currentConnector = connector;
|
|
|
|
if (connector?.connector?.connected) {
|
|
const account = this.accounts.find(
|
|
(acc) =>
|
|
acc.address.toLowerCase() === address.toLowerCase() &&
|
|
acc.brandName === brandName
|
|
)!;
|
|
connector.status = WALLETCONNECT_STATUS_MAP.CONNECTED;
|
|
this.updateCurrentStatus(WALLETCONNECT_STATUS_MAP.CONNECTED, account);
|
|
this.onAfterConnect?.(null, {
|
|
params: [{ accounts: [account.address], chainId: connector.chainId }]
|
|
});
|
|
} else if (connector) {
|
|
connector.status = WALLETCONNECT_STATUS_MAP.PENDING;
|
|
}
|
|
|
|
if (connector?.connector?.uri) {
|
|
this.emit('inited', connector.connector.uri);
|
|
}
|
|
|
|
return connector;
|
|
};
|
|
|
|
getConnectorStatus = (address: string, brandName: string) => {
|
|
const connector = this.connectors[`${brandName}-${address.toLowerCase()}`];
|
|
if (connector) {
|
|
return connector.status;
|
|
}
|
|
return null;
|
|
};
|
|
|
|
// pull the transaction current state, then resolve or reject
|
|
async signTransaction(
|
|
address,
|
|
transaction: TypedTransaction,
|
|
{ brandName = 'JADE' }: { brandName: string }
|
|
) {
|
|
const account = this.accounts.find(
|
|
(acct) =>
|
|
acct.address.toLowerCase() === address.toLowerCase() &&
|
|
acct.brandName === brandName
|
|
);
|
|
if (!account) {
|
|
throw new Error('Can not find this address');
|
|
}
|
|
|
|
const txData: JsonTx = {
|
|
to: transaction.to!.toString(),
|
|
value: convertToBigint(transaction.value),
|
|
data: bufferToHex(transaction.data),
|
|
nonce: convertToBigint(transaction.nonce),
|
|
gasLimit: convertToBigint(transaction.gasLimit),
|
|
gasPrice:
|
|
typeof (transaction as Transaction).gasPrice !== 'undefined'
|
|
? convertToBigint((transaction as Transaction).gasPrice)
|
|
: convertToBigint(
|
|
(transaction as FeeMarketEIP1559Transaction).maxFeePerGas
|
|
)
|
|
};
|
|
const txChainId = getChainId(transaction.common);
|
|
this.onAfterConnect = async (error?, payload?) => {
|
|
if (error) {
|
|
this.updateCurrentStatus(
|
|
WALLETCONNECT_STATUS_MAP.FAILD,
|
|
account,
|
|
error
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (!this.currentConnector) throw new Error('No connector avaliable');
|
|
|
|
this.updateCurrentStatus(
|
|
WALLETCONNECT_STATUS_MAP.CONNECTED,
|
|
account,
|
|
payload
|
|
);
|
|
|
|
if (payload) {
|
|
const { accounts, chainId } = payload.params[0];
|
|
if (
|
|
accounts[0].toLowerCase() !== address.toLowerCase() ||
|
|
chainId !== txChainId
|
|
) {
|
|
this.updateCurrentStatus(WALLETCONNECT_STATUS_MAP.FAILD, account, {
|
|
message: 'Wrong address or chainId',
|
|
code:
|
|
accounts[0].toLowerCase() === address.toLowerCase() ? 1000 : 1001
|
|
});
|
|
return;
|
|
}
|
|
this.currentConnector.chainId = chainId;
|
|
}
|
|
try {
|
|
const result = await this.currentConnector.connector.sendTransaction({
|
|
data: this._normalize(txData.data),
|
|
from: address,
|
|
gas: this._normalize(txData.gasLimit),
|
|
gasPrice: this._normalize(txData.gasPrice),
|
|
nonce: this._normalize(txData.nonce),
|
|
to: this._normalize(txData.to),
|
|
value: this._normalize(txData.value) || '0x0' // prevent 0x
|
|
});
|
|
this.resolvePromise!(result);
|
|
this.updateCurrentStatus(
|
|
WALLETCONNECT_STATUS_MAP.SIBMITTED,
|
|
account,
|
|
result
|
|
);
|
|
} catch (e) {
|
|
this.updateCurrentStatus(WALLETCONNECT_STATUS_MAP.REJECTED, account, e);
|
|
}
|
|
};
|
|
|
|
this.onDisconnect = (error, payload) => {
|
|
if (!this.currentConnector) throw new Error('No connector avaliable');
|
|
this.updateCurrentStatus(
|
|
WALLETCONNECT_STATUS_MAP.FAILD,
|
|
error || payload.params[0]
|
|
);
|
|
this._closeConnector(this.currentConnector.connector, address, brandName);
|
|
};
|
|
|
|
await this.init(account.address, account.brandName);
|
|
|
|
return new Promise((resolve, reject) => {
|
|
this.resolvePromise = resolve;
|
|
this.rejectPromise = reject;
|
|
});
|
|
}
|
|
|
|
async signPersonalMessage(
|
|
address: string,
|
|
message: string,
|
|
{ brandName = 'JADE' }: { brandName: string }
|
|
) {
|
|
const account = this.accounts.find(
|
|
(acct) =>
|
|
acct.address.toLowerCase() === address.toLowerCase() &&
|
|
acct.brandName === brandName
|
|
);
|
|
if (!account) {
|
|
throw new Error('Can not find this address');
|
|
}
|
|
|
|
this.onAfterConnect = async (error?, payload?) => {
|
|
if (error) {
|
|
this.updateCurrentStatus(
|
|
WALLETCONNECT_STATUS_MAP.FAILD,
|
|
account,
|
|
error
|
|
);
|
|
return;
|
|
}
|
|
if (!this.currentConnector) throw new Error('No connector avaliable');
|
|
const { accounts } = payload.params[0];
|
|
if (payload) {
|
|
if (accounts[0].toLowerCase() !== address.toLowerCase()) {
|
|
this.updateCurrentStatus(WALLETCONNECT_STATUS_MAP.FAILD, account, {
|
|
message: 'Wrong address or chainId',
|
|
code:
|
|
accounts[0].toLowerCase() === address.toLowerCase() ? 1000 : 1001
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
try {
|
|
this.updateCurrentStatus(WALLETCONNECT_STATUS_MAP.CONNECTED, payload);
|
|
|
|
const result =
|
|
await this.currentConnector.connector.signPersonalMessage([
|
|
message,
|
|
address
|
|
]);
|
|
this.resolvePromise!(result);
|
|
this.updateCurrentStatus(
|
|
WALLETCONNECT_STATUS_MAP.SIBMITTED,
|
|
account,
|
|
result
|
|
);
|
|
} catch (e) {
|
|
this.updateCurrentStatus(WALLETCONNECT_STATUS_MAP.REJECTED, account, e);
|
|
}
|
|
};
|
|
|
|
this.onDisconnect = (error, payload) => {
|
|
if (!this.currentConnector) throw new Error('No connector avaliable');
|
|
|
|
this.updateCurrentStatus(
|
|
WALLETCONNECT_STATUS_MAP.FAILD,
|
|
error || payload.params[0]
|
|
);
|
|
this._closeConnector(this.currentConnector.connector, address, brandName);
|
|
};
|
|
|
|
await this.init(account.address, account.brandName);
|
|
|
|
return new Promise((resolve) => {
|
|
this.resolvePromise = resolve;
|
|
});
|
|
}
|
|
|
|
async signTypedData(
|
|
address: string,
|
|
data,
|
|
{ brandName = 'JADE' }: { brandName: string }
|
|
) {
|
|
const account = this.accounts.find(
|
|
(acct) =>
|
|
acct.address.toLowerCase() === address.toLowerCase() &&
|
|
acct.brandName === brandName
|
|
);
|
|
if (!account) {
|
|
throw new Error('Can not find this address');
|
|
}
|
|
|
|
this.onAfterConnect = async (error, payload) => {
|
|
if (error) {
|
|
this.updateCurrentStatus(
|
|
WALLETCONNECT_STATUS_MAP.FAILD,
|
|
account,
|
|
error
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (!this.currentConnector) throw new Error('No connector avaliable');
|
|
|
|
if (payload) {
|
|
const { accounts } = payload.params[0];
|
|
if (accounts[0].toLowerCase() !== address.toLowerCase()) {
|
|
this.updateCurrentStatus(WALLETCONNECT_STATUS_MAP.FAILD, account, {
|
|
message: 'Wrong address or chainId',
|
|
code:
|
|
accounts[0].toLowerCase() === address.toLowerCase() ? 1000 : 1001
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
|
|
try {
|
|
this.updateCurrentStatus(
|
|
WALLETCONNECT_STATUS_MAP.CONNECTED,
|
|
account,
|
|
payload
|
|
);
|
|
|
|
const result = await this.currentConnector.connector.signTypedData([
|
|
address,
|
|
typeof data === 'string' ? data : JSON.stringify(data)
|
|
]);
|
|
this.resolvePromise!(result);
|
|
this.updateCurrentStatus(
|
|
WALLETCONNECT_STATUS_MAP.SIBMITTED,
|
|
account,
|
|
result
|
|
);
|
|
} catch (e) {
|
|
this.updateCurrentStatus(WALLETCONNECT_STATUS_MAP.REJECTED, account, e);
|
|
}
|
|
};
|
|
|
|
this.onDisconnect = (error, payload) => {
|
|
if (!this.currentConnector) throw new Error('No connector avaliable');
|
|
this.updateCurrentStatus(
|
|
WALLETCONNECT_STATUS_MAP.FAILD,
|
|
account,
|
|
error || payload.params[0]
|
|
);
|
|
this._closeConnector(this.currentConnector.connector, address, brandName);
|
|
};
|
|
|
|
await this.init(account.address, account.brandName);
|
|
|
|
return new Promise((resolve) => {
|
|
this.resolvePromise = resolve;
|
|
});
|
|
}
|
|
|
|
_close(address: string, brandName: string, silent?: boolean) {
|
|
const connector = this.connectors[`${brandName}-${address.toLowerCase()}`];
|
|
if (connector) {
|
|
this._closeConnector(connector.connector, address, brandName, silent);
|
|
}
|
|
}
|
|
|
|
updateCurrentStatus(status: number, account: Account | null, payload?: any) {
|
|
if (
|
|
(status === WALLETCONNECT_STATUS_MAP.REJECTED ||
|
|
status === WALLETCONNECT_STATUS_MAP.FAILD) &&
|
|
(this.currentConnectStatus === WALLETCONNECT_STATUS_MAP.FAILD ||
|
|
this.currentConnectStatus === WALLETCONNECT_STATUS_MAP.REJECTED ||
|
|
this.currentConnectStatus === WALLETCONNECT_STATUS_MAP.SIBMITTED)
|
|
) {
|
|
return;
|
|
}
|
|
this.currentConnectStatus = status;
|
|
|
|
const connector =
|
|
this.connectors[
|
|
`${account?.brandName}-${account?.address?.toLowerCase()}`
|
|
];
|
|
if (connector) {
|
|
connector.status = status;
|
|
}
|
|
|
|
this.emit('statusChange', {
|
|
status,
|
|
account: account || {
|
|
address: payload?.account
|
|
},
|
|
payload: {
|
|
...payload,
|
|
peer: {
|
|
metadata: payload?.peerMeta
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
updateSessionStatus: SDK['updateSessionStatus'] = (status, opt) => {
|
|
this.emit('sessionStatusChange', {
|
|
status,
|
|
...opt
|
|
});
|
|
};
|
|
|
|
_normalize(str) {
|
|
return sanitizeHex(str);
|
|
}
|
|
|
|
_checkBrandName(brandName, payload) {
|
|
const name = payload.params[0].peerMeta?.name;
|
|
// just check if brandName is in name or name is in brandName
|
|
let lowerName = name?.toLowerCase() as string;
|
|
if (!lowerName) {
|
|
this.emit(
|
|
'error',
|
|
new Error(
|
|
'[WalletConnect] No peerMeta name ' +
|
|
JSON.stringify(payload.params[0].peerMeta)
|
|
)
|
|
);
|
|
lowerName = brandName;
|
|
}
|
|
const peerName = BuildInWalletPeerName[brandName]?.toLowerCase() as
|
|
| string
|
|
| undefined;
|
|
if (IGNORE_CHECK_WALLET.includes(brandName)) return true;
|
|
|
|
if (peerName?.includes(lowerName) || lowerName?.includes(peerName ?? '')) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
getSessionStatus = (address: string, brandName: string) => {
|
|
const connector = this.connectors[`${brandName}-${address!.toLowerCase()}`];
|
|
|
|
if (!connector) {
|
|
return undefined;
|
|
}
|
|
|
|
return connector.sessionStatus;
|
|
};
|
|
|
|
getSessionAccount = (address: string, brandName: string) => {
|
|
const connector = this.connectors[`${brandName}-${address!.toLowerCase()}`];
|
|
|
|
if (!connector) {
|
|
return undefined;
|
|
}
|
|
|
|
return {
|
|
address,
|
|
brandName: connector.brandName,
|
|
chainId: connector.chainId,
|
|
deepLink: connector.connector.uri
|
|
};
|
|
};
|
|
|
|
getSessionNetworkDelay = (address: string, brandName: string) => {
|
|
const connector = this.connectors[`${brandName}-${address.toLowerCase()}`];
|
|
if (connector) {
|
|
return connector.networkDelay;
|
|
}
|
|
return null;
|
|
};
|
|
|
|
resend = () => {
|
|
this.onAfterConnect?.(...this.currentConnectParams);
|
|
};
|
|
|
|
switchEthereumChain = () => {
|
|
throw new Error('Method not implemented.');
|
|
};
|
|
}
|