Files
2024-07-26 15:53:05 +10:00

261 lines
14 KiB
JavaScript

"use strict";
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _CoinbaseKeyring_instances, _CoinbaseKeyring_accounts, _CoinbaseKeyring_sessions, _CoinbaseKeyring_initRelay, _CoinbaseKeyring_emit;
Object.defineProperty(exports, "__esModule", { value: true });
exports.LINK_API_URL = void 0;
const CoinbaseWalletProvider_1 = require("@coinbase/wallet-sdk/dist/provider/CoinbaseWalletProvider");
const WalletLinkRelay_1 = require("@coinbase/wallet-sdk/dist/relay/WalletLinkRelay");
const WalletSDKRelayEventManager_1 = require("@coinbase/wallet-sdk/dist/relay/WalletSDKRelayEventManager");
const version_1 = require("@coinbase/wallet-sdk/dist/version");
// eslint-disable-next-line import/no-nodejs-modules
const events_1 = __importDefault(require("events"));
// eslint-disable-next-line import/no-extraneous-dependencies
const uuid_1 = require("uuid");
const relay_ui_1 = require("./relay-ui");
const storage_1 = require("./storage");
const TYPE = 'Coinbase';
exports.LINK_API_URL = 'https://www.walletlink.org';
class CoinbaseKeyring extends events_1.default {
constructor(options = {}) {
super();
_CoinbaseKeyring_instances.add(this);
_CoinbaseKeyring_accounts.set(this, void 0);
_CoinbaseKeyring_sessions.set(this, {});
this.type = TYPE;
__classPrivateFieldSet(this, _CoinbaseKeyring_accounts, [], "f");
/* istanbul ignore next: It's not possible to write a unit test for this, because a constructor isn't allowed
* to be async. Jest can't await the constructor, and when the error gets thrown, Jest can't catch it. */
this.deserialize(options).catch((error) => {
throw new Error(`Problem deserializing CoinbaseKeyring ${error.message}`);
});
}
async serialize() {
return Promise.resolve({
accounts: __classPrivateFieldGet(this, _CoinbaseKeyring_accounts, "f"),
});
}
async deserialize(options) {
if (options.accounts) {
__classPrivateFieldSet(this, _CoinbaseKeyring_accounts, options.accounts, "f");
}
}
setAccountToAdd(account) {
this.accountToAdd = account.toLowerCase();
}
async addAccounts() {
if (!this.accountToAdd) {
throw new Error('No account to add');
}
if (__classPrivateFieldGet(this, _CoinbaseKeyring_accounts, "f").find((a) => a.toLowerCase() === this.accountToAdd)) {
const sessionData = Object.values(__classPrivateFieldGet(this, _CoinbaseKeyring_sessions, "f")).find((data) => { var _a; return ((_a = data.account) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === this.accountToAdd; });
if (sessionData) {
__classPrivateFieldGet(this, _CoinbaseKeyring_instances, "m", _CoinbaseKeyring_emit).call(this, sessionData, 'ADDRESS_DUPLICATE');
sessionData.provider.disconnect();
}
throw new Error("The address you're are trying to import is duplicate");
}
__classPrivateFieldGet(this, _CoinbaseKeyring_accounts, "f").push(this.accountToAdd);
return Promise.resolve(__classPrivateFieldGet(this, _CoinbaseKeyring_accounts, "f"));
}
async getAccounts() {
return Promise.resolve(__classPrivateFieldGet(this, _CoinbaseKeyring_accounts, "f"));
}
async signTransaction(address, transaction) {
var _a;
const sessionData = Object.values(__classPrivateFieldGet(this, _CoinbaseKeyring_sessions, "f")).find((data) => { var _a; return ((_a = data.account) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === address.toLowerCase(); });
if (!sessionData) {
throw new Error('No session data found');
}
const { provider } = sessionData;
const txData = {
to: (_a = transaction.to) === null || _a === void 0 ? void 0 : _a.toString(),
value: `0x${transaction.value.toString('hex')}`,
data: `0x${transaction.data.toString('hex')}`,
nonce: `0x${transaction.nonce.toString('hex')}`,
gasLimit: `0x${transaction.gasLimit.toString('hex')}`,
gasPrice: `0x${transaction.gasPrice
? transaction.gasPrice.toString('hex')
: transaction
.maxFeePerGas.toString('hex')}`,
};
const tx = await provider.request({
method: 'eth_sendTransaction',
params: [txData],
});
return tx;
}
async signMessage(address, message) {
const sessionData = Object.values(__classPrivateFieldGet(this, _CoinbaseKeyring_sessions, "f")).find((data) => { var _a; return ((_a = data.account) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === address.toLowerCase(); });
if (!sessionData) {
throw new Error('No session data found');
}
const { provider } = sessionData;
const response = await provider.request({
method: 'eth_sign',
params: [address, message],
});
return response;
}
// For personal_sign, we need to prefix the message:
async signPersonalMessage(address, msgHex) {
const sessionData = Object.values(__classPrivateFieldGet(this, _CoinbaseKeyring_sessions, "f")).find((data) => { var _a; return ((_a = data.account) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === address.toLowerCase(); });
if (!sessionData) {
throw new Error('No session data found');
}
const { provider } = sessionData;
const response = await provider.request({
method: 'personal_sign',
params: [msgHex, address],
});
return response;
}
// personal_signTypedData, signs data along with the schema
async signTypedData(address, typedData, opts = {
version: 'V1',
}) {
var _a, _b;
const sessionData = Object.values(__classPrivateFieldGet(this, _CoinbaseKeyring_sessions, "f")).find((data) => { var _a; return ((_a = data.account) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === address.toLowerCase(); });
if (!sessionData) {
throw new Error('No session data found');
}
const { provider } = sessionData;
const method = `eth_signTypedData_${(_b = (_a = opts.version) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : 'v1'}`;
const response = await provider.request({
method,
params: opts.version === 'V1' ? [[typedData], address] : [address, typedData],
});
return response;
}
removeAccount(address) {
__classPrivateFieldSet(this, _CoinbaseKeyring_accounts, __classPrivateFieldGet(this, _CoinbaseKeyring_accounts, "f").filter((account) => account.toLowerCase() !== address.toLowerCase()), "f");
Object.entries(__classPrivateFieldGet(this, _CoinbaseKeyring_sessions, "f")).find(([_, sessionData]) => {
var _a;
if (((_a = sessionData.account) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === address.toLowerCase()) {
sessionData.provider.disconnect();
return true;
}
return false;
});
}
connect(opts) {
const options = Object.assign({ appName: 'Lux', appIcon: 'https://static-assets.rabby.io/files/122da969-da58-42e9-ab39-0a8dd38d94b8.png' }, opts);
const { provider, relay } = __classPrivateFieldGet(this, _CoinbaseKeyring_instances, "m", _CoinbaseKeyring_initRelay).call(this, options);
provider.on('disconnect', () => {
const sessionData = __classPrivateFieldGet(this, _CoinbaseKeyring_sessions, "f")[relay.session.id];
if (sessionData) {
__classPrivateFieldGet(this, _CoinbaseKeyring_instances, "m", _CoinbaseKeyring_emit).call(this, sessionData, 'DISCONNECTED');
}
});
provider.on('accountsChanged', (accounts) => {
const sessionData = __classPrivateFieldGet(this, _CoinbaseKeyring_sessions, "f")[relay.session.id];
if (!sessionData) {
return;
}
const account = accounts[0];
if ((opts === null || opts === void 0 ? void 0 : opts.address) &&
opts.address.toLowerCase() !== account.toLowerCase()) {
sessionData.account = opts.address;
__classPrivateFieldGet(this, _CoinbaseKeyring_instances, "m", _CoinbaseKeyring_emit).call(this, sessionData, 'ACCOUNT_ERROR');
return;
}
if (!sessionData.account) {
sessionData.account = account;
__classPrivateFieldGet(this, _CoinbaseKeyring_instances, "m", _CoinbaseKeyring_emit).call(this, sessionData, 'CONNECTED');
return;
}
sessionData.account = account;
__classPrivateFieldGet(this, _CoinbaseKeyring_instances, "m", _CoinbaseKeyring_emit).call(this, sessionData, 'ACCOUNT_CHANGED');
});
provider.on('chainChanged', (chainId) => {
const sessionData = __classPrivateFieldGet(this, _CoinbaseKeyring_sessions, "f")[relay.session.id];
if (sessionData) {
sessionData.chainId = chainId;
__classPrivateFieldGet(this, _CoinbaseKeyring_instances, "m", _CoinbaseKeyring_emit).call(this, sessionData, 'CONNECTED');
}
});
provider.on('message', (info) => {
console.log('message', info);
});
provider
.request({
method: 'eth_requestAccounts',
})
.then((accounts) => {
const sessionData = __classPrivateFieldGet(this, _CoinbaseKeyring_sessions, "f")[relay.session.id];
if (sessionData) {
sessionData.account = accounts[0];
__classPrivateFieldGet(this, _CoinbaseKeyring_instances, "m", _CoinbaseKeyring_emit).call(this, sessionData, 'CONNECTED');
}
})
.catch((error) => {
console.error(error);
});
return provider.qrUrl;
}
getSessionStatus(address) {
const sessionData = Object.values(__classPrivateFieldGet(this, _CoinbaseKeyring_sessions, "f")).find((data) => { var _a; return ((_a = data.account) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === address.toLowerCase(); });
return sessionData === null || sessionData === void 0 ? void 0 : sessionData.status;
}
getSessionAccount(address) {
const sessionData = Object.values(__classPrivateFieldGet(this, _CoinbaseKeyring_sessions, "f")).find((data) => { var _a; return ((_a = data.account) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === address.toLowerCase(); });
return {
chainId: sessionData === null || sessionData === void 0 ? void 0 : sessionData.chainId,
account: sessionData === null || sessionData === void 0 ? void 0 : sessionData.account,
status: sessionData === null || sessionData === void 0 ? void 0 : sessionData.status,
};
}
closeConnector({ address }, silent) {
const sessionData = Object.values(__classPrivateFieldGet(this, _CoinbaseKeyring_sessions, "f")).find((data) => { var _a; return ((_a = data.account) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === address.toLowerCase(); });
if (sessionData) {
sessionData.provider.disconnect();
}
}
}
exports.default = CoinbaseKeyring;
_CoinbaseKeyring_accounts = new WeakMap(), _CoinbaseKeyring_sessions = new WeakMap(), _CoinbaseKeyring_instances = new WeakSet(), _CoinbaseKeyring_initRelay = function _CoinbaseKeyring_initRelay(opts) {
var _a;
const relayEventManager = new WalletSDKRelayEventManager_1.WalletSDKRelayEventManager();
const id = (_a = opts === null || opts === void 0 ? void 0 : opts.address) !== null && _a !== void 0 ? _a : (0, uuid_1.v4)();
const storage = new storage_1.MemoryStorage(`coinbase:${id}`);
const defaultRelayOptions = {
linkAPIUrl: exports.LINK_API_URL,
version: version_1.LIB_VERSION,
darkMode: false,
storage,
relayEventManager,
uiConstructor: () => new relay_ui_1.HeadlessUI(),
};
const relay = new WalletLinkRelay_1.WalletLinkRelay(defaultRelayOptions);
const provider = new CoinbaseWalletProvider_1.CoinbaseWalletProvider({
relayProvider: async () => Promise.resolve(relay),
relayEventManager,
storage,
jsonRpcUrl: '',
chainId: 1,
qrUrl: relay.getQRCodeUrl(),
overrideIsCoinbaseWallet: true,
overrideIsCoinbaseBrowser: true,
overrideIsMetaMask: true,
});
relay.setAppInfo(opts.appName, opts.appIcon);
__classPrivateFieldGet(this, _CoinbaseKeyring_sessions, "f")[relay.session.id] = { provider, status: 'DISCONNECTED' };
return { relay, provider };
}, _CoinbaseKeyring_emit = function _CoinbaseKeyring_emit(sessionData, status, payload) {
sessionData.status = status;
this.emit('message', Object.assign(Object.assign({}, payload), { status, account: sessionData === null || sessionData === void 0 ? void 0 : sessionData.account, chainId: sessionData.chainId }));
};
CoinbaseKeyring.type = TYPE;
//# sourceMappingURL=coinbase-keyring.js.map