@minswap/wc-dapp
Version:
Wallet connect integration for Cardano dApps
537 lines (536 loc) • 16.7 kB
JavaScript
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
};