UNPKG

@minswap/wc-dapp

Version:

Wallet connect integration for Cardano dApps

537 lines (536 loc) 16.7 kB
var k = Object.defineProperty; var U = (t, e, s) => e in t ? k(t, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : t[e] = s; var i = (t, e, s) => U(t, typeof e != "symbol" ? e + "" : e, s); import a from "@minswap/tiny-invariant"; import { WalletConnectModal as I } from "@walletconnect/modal"; import G from "@walletconnect/universal-provider"; import x from "events"; const M = "error", $ = "wc", B = 2, j = "cardano_provider", T = `${$}@${B}:${j}:`, g = "defaultAccount"; var q = /* @__PURE__ */ ((t) => (t.DEFAULT = "wss://relay.walletconnect.org", t.US = "wss://us-east-1.relay.walletconnect.com/", t.EU = "wss://eu-central-1.relay.walletconnect.com/", t.APAC = "wss://ap-southeast-1.relay.walletconnect.com/", t))(q || {}); const L = [ "33c036d8075d28c9f3619d4d43075676a6d294047e3658fb103e5b3424337551", "a78c2c969af82bc38a9c8fbe8ad9ee682d9c8c76b1a5d0f167e8f90975c3e0c8" ]; class E extends Error { constructor(s) { super(s); i(this, "error"); Object.setPrototypeOf(this, E.prototype); } } class w extends Error { constructor(s) { super(s); i(this, "error"); Object.setPrototypeOf(this, w.prototype); } } class S extends Error { constructor(s) { super(s); i(this, "error"); Object.setPrototypeOf(this, S.prototype); } } class C extends Error { constructor(s) { super(s); i(this, "error"); Object.setPrototypeOf(this, C.prototype); } } class b extends Error { constructor(s) { super(s); i(this, "error"); Object.setPrototypeOf(this, b.prototype); } } class y extends Error { constructor(s) { super(s); i(this, "error"); Object.setPrototypeOf(this, y.prototype); } } var W = /* @__PURE__ */ ((t) => (t[t.TESTNET = 0] = "TESTNET", t[t.MAINNET = 1] = "MAINNET", t))(W || {}); const o = "cip34"; var X = /* @__PURE__ */ ((t) => (t.MAINNET = "cip34:1-764824073", t.TESTNET_PREPROD = "cip34:0-1", t.TESTNET_PREVIEW = "cip34:0-2", t))(X || {}); const z = { "cip34:1-764824073": { type: o, networkId: 1, protocolMagic: "764824073", name: "Cardano Mainnet", id: "1-764824073" } }, K = { "cip34:0-1": { type: o, networkId: 0, protocolMagic: "1", name: "Cardano Testnet Preprod", id: "0-1" }, "cip34:0-2": { type: o, networkId: 0, protocolMagic: "2", name: "Cardano Testnet Preview", id: "0-2" } }, f = { ...z, ...K }; var v = /* @__PURE__ */ ((t) => (t.CARDANO_SIGN_TRANSACTION = "cardano_signTx", t.CARDANO_SIGN_DATA = "cardano_signData", t))(v || {}), c = /* @__PURE__ */ ((t) => (t.CARDANO_GET_UNUSED_ADDRESSES = "cardano_getUnusedAddresses", t.CARDANO_GET_USED_ADDRESSES = "cardano_getUsedAddresses", t.CARDANO_GET_CHANGE_ADDRESSES = "cardano_getChangeAddress", t.CARDANO_GET_NETWORK_ID = "cardano_getNetworkId", t.CARDANO_GET_COLLATERAL = "cardano_getCollateral", t.CARDANO_GET_REWARD_ADDRESS = "cardano_getRewardAddress", t.CARDANO_GET_REWARD_ADDRESSES = "cardano_getRewardAddresses", t))(c || {}), _ = /* @__PURE__ */ ((t) => (t.CARDANO_GET_BALANCE = "cardano_getBalance", t.CARDANO_GET_UTXOS = "cardano_getUtxos", t.CARDANO_SUBMIT_TX = "cardano_submitTx", t))(_ || {}), h = /* @__PURE__ */ ((t) => (t.NETWORK_CHANGE = "chainChanged", t.ACCOUNT_CHANGE = "accountsChanged", t))(h || {}); const N = (t) => f[t].networkId, R = [ ...Object.values(v), ...Object.values(c), ...Object.values(_) ], O = Object.values(h), F = (t, e) => ({ [o]: { chains: t, methods: R, events: e ? [] : O, // TODO: Fix this in universal provider // Hack: since universal provider doesn't allow addition of new rpc url when a new chain selection rpcMap: D(Object.keys(f)) } }); function J(t) { return `https://rpc.walletconnect.com/v1?chainId=${t}`; } const D = (t) => { const e = {}; for (const s of t) e[f[s].id] = J(s); return e; }, H = (t, e) => ({ [o]: { chains: t, methods: R, events: e ? [] : O, rpcMap: D(t) } }); class V { constructor(e) { i(this, "_provider"); i(this, "_chain"); i(this, "_baseAddress"); i(this, "_stakeAddress"); i(this, "_rpc"); i(this, "_networkId"); i(this, "_sam"); i(this, "events", new x()); this._provider = e.provider, this._chain = e.chain, this._networkId = N(e.chain), this._rpc = e.rpc, this._stakeAddress = e.stakeAddress, this._baseAddress = e.baseAddress, this._sam = e.sam; } set chain(e) { this._chain = e, this._networkId = N(e), this._rpc.changeNetwork = this._networkId; } set baseAddress(e) { this._baseAddress = e ?? ""; } set stakeAddress(e) { this._stakeAddress = e; } set setSam(e) { this._sam = e; } get isSam() { return this._sam; } async getNetworkId() { return this._sam ? Promise.resolve(this._networkId) : this._provider.request( { method: c.CARDANO_GET_NETWORK_ID }, this._chain ); } async getUtxos(e, s) { return this._sam ? this._rpc.getUtxos({ address: this._baseAddress, network: this._networkId }) : this._provider.request( { method: _.CARDANO_GET_UTXOS, params: [e, s] }, this._chain ); } async getBalance() { return this._sam ? this._rpc.getBalance({ address: this._stakeAddress, network: this._networkId }) : this._provider.request( { method: _.CARDANO_GET_BALANCE }, this._chain ); } async getUsedAddresses() { return this._sam ? (a(this._baseAddress, "Base address must be defined"), Promise.resolve([this._baseAddress])) : this._provider.request( { method: c.CARDANO_GET_USED_ADDRESSES }, this._chain ); } async getUnusedAddresses() { return this._sam ? (a(this._baseAddress, "Base address must be defined"), Promise.resolve([this._baseAddress])) : this._provider.request( { method: c.CARDANO_GET_UNUSED_ADDRESSES }, this._chain ); } async getChangeAddress() { return this._sam ? (a(this._baseAddress, "Base address must be defined"), Promise.resolve(this._baseAddress)) : this._provider.request( { method: c.CARDANO_GET_CHANGE_ADDRESSES }, this._chain ); } async getRewardAddress() { return this._sam ? (a(this._stakeAddress, "Stake address must be defined"), Promise.resolve(this._stakeAddress)) : this._provider.request( { method: c.CARDANO_GET_REWARD_ADDRESS }, this._chain ); } async getRewardAddresses() { return this._sam ? (a(this._stakeAddress, "Stake address must be defined"), Promise.resolve([this._stakeAddress])) : this._provider.request( { method: c.CARDANO_GET_REWARD_ADDRESSES }, this._chain ); } async signTx(e, s = !1) { return this._provider.request( { method: v.CARDANO_SIGN_TRANSACTION, params: [e, s] }, this._chain ); } async signData(e, s) { return this._provider.request( { method: v.CARDANO_SIGN_DATA, params: [e, s] }, this._chain ); } async submitTx(e) { return this._sam ? this._rpc.submitTx({ tx: e, network: this._networkId }) : this._provider.request( { method: _.CARDANO_SUBMIT_TX, params: [e] }, this._chain ); } async getCollateral() { return this._sam ? Promise.resolve([]) : this._provider.request( { method: c.CARDANO_GET_COLLATERAL }, this._chain ); } async onAccountChange(e) { return new Promise((s, r) => { try { this.events.on(h.ACCOUNT_CHANGE, e), s(); } catch (n) { r(n); } }); } async onNetworkChange(e) { return new Promise((s, r) => { try { this.events.on(h.NETWORK_CHANGE, e), s(); } catch (n) { r(n); } }); } } class P { constructor({ provider: e, modal: s, chains: r, rpc: n, legacyMode: d }) { i(this, "modal"); i(this, "chains"); i(this, "rpc"); i(this, "provider"); i(this, "enabledApi"); i(this, "legacyMode"); i(this, "onDisplayUri", (e) => { var s, r; console.info("pairing uri", e), (s = this.modal) == null || s.closeModal(), (r = this.modal) == null || r.openModal({ uri: e }); }); i(this, "onSessionDelete", () => { this.reset(); }); i(this, "onSessionPing", (e) => { console.info("session_ping", e); }); i(this, "onSessionEvent", async (e) => { const s = e.params.event.name; s === h.NETWORK_CHANGE ? await this.onChainChange(e.params.event.data) : s === h.ACCOUNT_CHANGE && await this.onAccountChange(e.params.event.data); }); i(this, "onAccountChange", async (e) => { if (await this.isEnabled()) { a(this.enabledApi, "Enabled API not initialized"); const r = e.split(":")[2].split("-")[0], n = e.split(":")[2].split("-")[1]; this.enabledApi.baseAddress = n, this.enabledApi.stakeAddress = r, this.enabledApi.events.emit(h.ACCOUNT_CHANGE, e), await this.persist(g, e); } }); i(this, "onChainChange", async (e) => { if (await this.isEnabled()) { a(this.enabledApi, "Enabled API not initialized"); const r = e.split(":")[1], n = e.split(":")[2].split("-")[0], d = e.split(":")[2].split("-")[1]; this.enabledApi.chain = `${o}:${r}`, this.enabledApi.baseAddress = d, this.enabledApi.stakeAddress = n, this.enabledApi.events.emit(h.NETWORK_CHANGE, e), await this.persist(g, e); } }); i(this, "onSessionUpdate", (e) => { console.info("session_update", e); }); this.chains = r, this.provider = e, this.modal = s, this.rpc = n, this.registerEventListeners(), this.legacyMode = d; } static async init(e) { a(e.projectId.length > 0, "Wallet Connect project ID not set"); const s = await G.init({ logger: M, relayUrl: e.relayerRegion, projectId: e.projectId, metadata: e.metadata }); let r; const { qrcode: n, chains: d, legacyMode: p, rpc: l } = e; return n && (r = Y(e.projectId, e.chains)), new P({ provider: s, modal: r, chains: d, rpc: l, legacyMode: p }); } async enable(e) { var r; if (((r = this.provider) == null ? void 0 : r.session) ? await this.loadPersistedSession(e) : await this.connect({ sam: e }), !this.provider) throw new E("Provider not initialized"); if (!this.enabledApi) throw new w("Enabled API not initialized"); return this.enabledApi; } getDefaultChainId() { var r, n; const e = this.getProvider(), s = ((r = e.namespaces) == null ? void 0 : r[o].defaultChain) || ((n = e.namespaces) == null ? void 0 : n[o].chains[0].split(":")[1]); if (!s) throw new S("Default chain not set"); return s; } async getDefaultAccount() { var r, n; const e = this.getProvider(), s = await this.getFromStore(g) || ((n = (r = e.session) == null ? void 0 : r.namespaces) == null ? void 0 : n[o].accounts[0]); if (!s) throw new C("No account set"); return s; } getProvider() { if (!this.provider) throw new E("Provider not initialized. Call init() first"); return this.provider; } async disconnect() { const e = this.getProvider(); if (e.session) try { await e.disconnect(); } catch (s) { if (console.info("disconnect error", s.message), !/No matching key/i.test(s.message)) throw s; } finally { this.removeListeners(), this.reset(); } } async isEnabled() { return Promise.resolve(!!this.enabledApi); } async loadPersistedSession(e) { const s = this.getProvider(); a(s.session, "Provider not initialized. Call init() first"); const r = this.getDefaultChainId(), d = (await this.getDefaultAccount()).split(":")[2].split("-"), p = d[0], l = d[1], u = this.legacyMode ? !1 : e; this.enabledApi = new V({ provider: s, chain: `${o}:${r}`, rpc: this.rpc, stakeAddress: p, baseAddress: l, sam: u }); } async connect(e = {}) { a(this.chains, "Chain not set. Call init() first"); const s = this.getProvider(), r = F(this.chains, this.legacyMode), n = H(this.chains, this.legacyMode); try { if (!await new Promise((p, l) => { var u; (u = this.modal) == null || u.subscribeModal(async (A) => { !A.open && !s.session && (s.abortPairingAttempt(), await s.cleanupPendingPairings({ deletePairings: !0 }), this.reset(), l(new b("Connection aborted by user."))); }), s == null || s.connect({ namespaces: { ...r }, optionalNamespaces: { ...n }, pairingTopic: e.pairingTopic }).then((A) => { p(A); }).catch((A) => { this.reset(), l(A); }); })) return; await this.loadPersistedSession(e.sam); } finally { this.modal && this.modal.closeModal(); } } reset() { this.provider = void 0, this.enabledApi = void 0; } registerEventListeners() { const e = this.getProvider(); e.on("session_event", this.onSessionEvent), e.on("session_ping", this.onSessionPing), e.on("session_delete", this.onSessionDelete), e.on("display_uri", this.onDisplayUri), e.on("session_update", this.onSessionUpdate); } removeListeners() { const e = this.getProvider(); e.removeListener("session_event", this.onSessionEvent), e.removeListener("session_ping", this.onSessionPing), e.removeListener("session_delete", this.onSessionDelete), e.removeListener("display_uri", this.onDisplayUri), e.removeListener("session_update", this.onSessionUpdate); } async persist(e, s) { var r; await ((r = this.provider) == null ? void 0 : r.client.core.storage.setItem(`${T}/${e}`, s)); } async getFromStore(e) { var s; return await ((s = this.provider) == null ? void 0 : s.client.core.storage.getItem(`${T}/${e}`)); } } const Y = (t, e) => { try { return new I({ projectId: t, chains: e, enableExplorer: !0, explorerRecommendedWalletIds: L, explorerExcludedWalletIds: "ALL" }); } catch (s) { throw new y(`Error instantiating web3Modal: ${JSON.stringify(s)}`); } }; var m = /* @__PURE__ */ ((t) => (t.UTXO_BY_ADDRESS = "/wallet/utxo/address", t.BALANCE_BY_ADDRESS = "/wallet/balance/address", t.SUBMIT_TX = "/wallet/submitTx", t))(m || {}); class re { constructor({ networkId: e, url: s }) { i(this, "url"); i(this, "networkId"); this.networkId = e, this.url = s; } set changeNetwork(e) { this.networkId = e; } getProviderUrl() { return this.url[this.networkId]; } async makeGetCall({ path: e, params: s }) { const r = await fetch(`${this.getProviderUrl()}${e}` + s, { method: "GET" }); if (r.ok) return await r.text(); throw Error(`Unexpected error: ${r.statusText}`); } async makePostCall({ path: e, body: s }) { const r = await fetch(`${this.getProviderUrl()}${e}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: s }); if (r.ok) return await r.text(); throw Error(`Unexpected error: ${r.statusText}`); } async getUtxos({ address: e }) { const s = await this.makeGetCall({ path: `${m.UTXO_BY_ADDRESS}?`, params: new URLSearchParams({ address: e }) }); return JSON.parse(s); } async getBalance({ address: e }) { return await this.makeGetCall({ path: `${m.BALANCE_BY_ADDRESS}?`, params: new URLSearchParams({ address: e }) }); } async submitTx({ tx: e }) { return this.makePostCall({ path: m.SUBMIT_TX, body: JSON.stringify({ tx: e }) }); } } export { g as ACCOUNT, C as AccountNotSetError, f as CARDANO_CHAINS, z as CARDANO_MAINNET_CHAINS, o as CARDANO_NAMESPACE_NAME, _ as CARDANO_RPC_METHODS, v as CARDANO_SIGNING_METHODS, K as CARDANO_TEST_CHAINS, c as CARDANO_WALLET_METHODS, X as CHAIN, h as CHAIN_EVENTS, j as CONTEXT, P as CardanoProvider, b as ConnectionAbortedByUserError, re as DAppRpc, M as DEFAULT_LOGGER, S as DefaultChainNotSetError, m as ENDPOINTS, V as EnabledAPI, w as EnabledApiNotFoundError, W as NetworkID, $ as PROTOCOL, E as ProviderNotInitialisedError, q as REGIONALIZED_RELAYER_ENDPOINTS, O as SESSION_PROPOSAL_EVENTS, R as SESSION_PROPOSAL_METHODS, T as STORAGE, L as SUPPORTED_EXPLORER_WALLETS, B as WC_VERSION, y as Web3ModalInitError, J as chainToRpc, D as chainsToRpcMap, N as getNetworkIdFromChainId, H as getOptionalCardanoNamespace, F as getRequiredCardanoNamespace, Y as getWeb3Modal };