Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: scraps auto reconnect in Universal Provider #5661

Open
wants to merge 5 commits into
base: v2.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions packages/sign-client/src/controllers/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,14 +223,27 @@
pairingTopic: topic,
...(sessionProperties && { sessionProperties }),
};

const proposalId = payloadId();

const {
reject,
resolve,
done: approval,
} = createDelayedPromise<SessionTypes.Struct>(expiry, PROPOSAL_EXPIRY_MESSAGE);

const proposalExpireHandler = ({ id }: { id: number }) => {
if (id === proposalId) {
this.client.events.off("proposal_expire", proposalExpireHandler);
reject({ message: PROPOSAL_EXPIRY_MESSAGE, code: 0 });
}
};

this.client.events.on("proposal_expire", proposalExpireHandler);
this.events.once<"session_connect">(
engineEvent("session_connect"),
async ({ error, session }) => {
this.client.events.off("proposal_expire", proposalExpireHandler);
if (error) reject(error);
else if (session) {
session.self.publicKey = publicKey;
Expand All @@ -254,13 +267,14 @@
}
},
);
const id = await this.sendRequest({
await this.sendRequest({
topic,
method: "wc_sessionPropose",
params: proposal,
throwOnFailedPublish: true,
clientRpcId: proposalId,
});
await this.setProposal(id, { id, ...proposal });
await this.setProposal(proposalId, { id: proposalId, ...proposal });
return { uri, approval };
};

Expand Down Expand Up @@ -2116,7 +2130,7 @@
}, 500);
};

private onSessionDeleteRequest: EnginePrivate["onSessionDeleteRequest"] = async (

Check warning on line 2133 in packages/sign-client/src/controllers/engine.ts

View workflow job for this annotation

GitHub Actions / code_style (lint)

Async method 'onSessionDeleteRequest' has no 'await' expression
topic,
payload,
) => {
Expand Down
57 changes: 18 additions & 39 deletions providers/universal-provider/src/UniversalProvider.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import SignClient, { PROPOSAL_EXPIRY_MESSAGE } from "@walletconnect/sign-client";
import SignClient from "@walletconnect/sign-client";
import { SessionTypes } from "@walletconnect/types";
import { JsonRpcResult } from "@walletconnect/jsonrpc-types";
import { getSdkError, isValidArray, parseNamespaceKey } from "@walletconnect/utils";
Expand Down Expand Up @@ -53,8 +53,6 @@ export class UniversalProvider implements IUniversalProvider {
public logger: Logger;
public uri: string | undefined;

private shouldAbortPairingAttempt = false;
private maxPairingAttempts = 10;
private disableProviderPing = false;

static async init(opts: UniversalProviderOpts) {
Expand Down Expand Up @@ -187,44 +185,25 @@ export class UniversalProvider implements IUniversalProvider {
}

public async pair(pairingTopic: string | undefined): Promise<SessionTypes.Struct> {
this.shouldAbortPairingAttempt = false;
let pairingAttempts = 0;
do {
if (this.shouldAbortPairingAttempt) {
throw new Error("Pairing aborted");
}

if (pairingAttempts >= this.maxPairingAttempts) {
throw new Error("Max auto pairing attempts reached");
}
const { uri, approval } = await this.client.connect({
pairingTopic,
requiredNamespaces: this.namespaces,
optionalNamespaces: this.optionalNamespaces,
sessionProperties: this.sessionProperties,
});

const { uri, approval } = await this.client.connect({
pairingTopic,
requiredNamespaces: this.namespaces,
optionalNamespaces: this.optionalNamespaces,
sessionProperties: this.sessionProperties,
});
if (uri) {
this.uri = uri;
this.events.emit("display_uri", uri);
}

if (uri) {
this.uri = uri;
this.events.emit("display_uri", uri);
}
const session = await approval();
this.session = session;
// assign namespaces from session if not already defined
const approved = populateNamespacesChains(session.namespaces) as NamespaceConfig;
this.namespaces = mergeRequiredOptionalNamespaces(this.namespaces, approved);
this.persist("namespaces", this.namespaces);

await approval()
.then((session) => {
this.session = session;
// assign namespaces from session if not already defined
const approved = populateNamespacesChains(session.namespaces) as NamespaceConfig;
this.namespaces = mergeRequiredOptionalNamespaces(this.namespaces, approved);
this.persist("namespaces", this.namespaces);
})
.catch((error) => {
if (error.message !== PROPOSAL_EXPIRY_MESSAGE) {
throw error;
}
pairingAttempts++;
});
} while (!this.session);
this.onConnect();
return this.session;
}
Expand Down Expand Up @@ -265,7 +244,7 @@ export class UniversalProvider implements IUniversalProvider {
}

public abortPairingAttempt() {
this.shouldAbortPairingAttempt = true;
this.logger.warn("abortPairingAttempt is deprecated. This is now a no-op.");
}

// ---------- Private ----------------------------------------------- //
Expand Down
27 changes: 25 additions & 2 deletions providers/universal-provider/test/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { expect, describe, it, beforeAll, afterAll } from "vitest";
import { expect, describe, it, beforeAll, afterAll, vi } from "vitest";
import Web3 from "web3";
import { BigNumber, providers, utils } from "ethers";
import { TestNetwork } from "ethereum-test-network";
Expand Down Expand Up @@ -31,7 +31,6 @@ import {
import { getChainId, getGlobal, getRpcUrl, setGlobal } from "../src/utils";
import { BUNDLER_URL, RPC_URL } from "../src/constants";
import { formatJsonRpcResult } from "@walletconnect/jsonrpc-utils";
import { parseChainId } from "@walletconnect/utils";

const getDbName = (_prefix: string) => {
return `./test/tmp/${_prefix}.db`;
Expand Down Expand Up @@ -1261,6 +1260,30 @@ describe("UniversalProvider", function () {
expectedChainId,
});
});
it("should reject connect on proposal expiry", async () => {
const dapp = await UniversalProvider.init({
...TEST_PROVIDER_OPTS,
name: "dapp",
});

await Promise.all([
new Promise<void>(async (resolve) => {
await dapp.connect({}).catch((error) => {
expect(error.message).to.eql("Proposal expired");
expect(dapp.client.events.listenerCount("proposal_expire")).to.eql(0);
resolve();
});
}),
new Promise<void>(async (resolve) => {
await throttle(2_000);
expect(dapp.client.events.listenerCount("proposal_expire")).to.eql(1);
const proposals = dapp.client.proposal.getAll();
// force expiry of the proposal so the test doesn't wait for the default expiry time
dapp.client.core.expirer.set(proposals[0].id, 0);
resolve();
}),
]);
});
it("should cache `wallet_getCapabilities` request", async () => {
const dapp = await UniversalProvider.init({
...TEST_PROVIDER_OPTS,
Expand Down
Loading