Skip to content

feat: PoC on sign 2.5 methods #6647

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

Draft
wants to merge 4 commits into
base: v2.0
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion packages/core/src/constants/relayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export const RELAYER_DEFAULT_PROTOCOL = "irn";

export const RELAYER_DEFAULT_LOGGER = "error";

export const RELAYER_DEFAULT_RELAY_URL = "wss://relay.walletconnect.org";
export const RELAYER_DEFAULT_RELAY_URL = "wss://staging-relay.walletconnect.com";

export const RELAYER_CONTEXT = "relayer";

Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/controllers/pairing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,10 @@ export class Pairing implements IPairing {
this.events.emit(PAIRING_EVENTS.create, pairing);
this.core.expirer.set(topic, expiry);
await this.pairings.set(topic, pairing);
await this.core.relayer.subscribe(topic, { transportType: params?.transportType });
await this.core.relayer.subscribe(topic, {
transportType: params?.transportType,
internal: params?.internal,
});

return { topic, uri };
};
Expand Down
193 changes: 116 additions & 77 deletions packages/core/src/controllers/publisher.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* eslint-disable no-console */
import { HEARTBEAT_EVENTS } from "@walletconnect/heartbeat";
import { JsonRpcPayload, RequestArguments } from "@walletconnect/jsonrpc-types";
import { generateChildLogger, getLoggerContext, Logger } from "@walletconnect/logger";
import { RelayJsonRpc } from "@walletconnect/relay-api";
import { IPublisher, IRelayer, PublisherTypes, RelayerTypes } from "@walletconnect/types";
import { IPublisher, IRelayer, RelayerTypes } from "@walletconnect/types";
import {
getRelayProtocolApi,
getRelayProtocolName,
Expand All @@ -13,12 +14,15 @@ import { EventEmitter } from "events";

import { PUBLISHER_CONTEXT, PUBLISHER_DEFAULT_TTL, RELAYER_EVENTS } from "../constants";
import { getBigIntRpcId } from "@walletconnect/jsonrpc-utils";
import { ONE_MINUTE, ONE_SECOND, toMiliseconds } from "@walletconnect/time";
import { FIVE_MINUTES, ONE_MINUTE, ONE_SECOND, toMiliseconds } from "@walletconnect/time";

type IPublishType = PublisherTypes.Params & {
type IPublishType = {
attestation?: string;
attempt: number;
request: RequestArguments;
opts?: RelayerTypes.PublishOptions;
};

export class Publisher extends IPublisher {
public events = new EventEmitter();
public name = PUBLISHER_CONTEXT;
Expand Down Expand Up @@ -47,52 +51,49 @@ export class Publisher extends IPublisher {
this.logger.trace({ type: "method", method: "publish", params: { topic, message, opts } });

const ttl = opts?.ttl || PUBLISHER_DEFAULT_TTL;
const relay = getRelayProtocolName(opts);
const prompt = opts?.prompt || false;
const tag = opts?.tag || 0;
const id = opts?.id || (getBigIntRpcId().toString() as any);
const params = {
topic,
message,
opts: {

const api = getRelayProtocolApi(getRelayProtocolName().protocol);

const request: RequestArguments<RelayJsonRpc.PublishParams> = {
id,
method: opts?.publishMethod || api.publish,
params: {
topic,
message,
ttl,
relay,
prompt,
tag,
id,
attestation: opts?.attestation,
tvf: opts?.tvf,
...opts?.tvf,
},
};
const failedPublishMessage = `Failed to publish payload, please try again. id:${id} tag:${tag}`;

const failedPublishMessage = `Failed to publish payload, please try again. id:${id} tag:${tag}`;
console.log("publish params", opts);
try {
if (isUndefined(request.params?.prompt)) delete request.params?.prompt;
if (isUndefined(request.params?.tag)) delete request.params?.tag;

/**
* attempt to publish the payload for <initialPublishTimeout> seconds,
* if the publish fails, add the payload to the queue and it will be retried on every pulse
* until it is successfully published or <publishTimeout> seconds have passed
*/
const publishPromise = new Promise(async (resolve) => {
const publishPromise = new Promise<void>(async (resolve) => {
const onPublish = ({ id }: { id: string }) => {
if (params.opts.id === id) {
if (request.id?.toString() === id.toString()) {
this.removeRequestFromQueue(id);
this.relayer.events.removeListener(RELAYER_EVENTS.publish, onPublish);
resolve(params);
resolve();
}
};
this.relayer.events.on(RELAYER_EVENTS.publish, onPublish);
const initialPublish = createExpiringPromise(
new Promise((resolve, reject) => {
this.rpcPublish({
topic,
message,
ttl,
prompt,
tag,
id,
attestation: opts?.attestation,
tvf: opts?.tvf,
})
this.rpcPublish(request, opts)
.then(resolve)
.catch((e) => {
this.logger.warn(e, e?.message);
Expand All @@ -106,7 +107,7 @@ export class Publisher extends IPublisher {
await initialPublish;
this.events.removeListener(RELAYER_EVENTS.publish, onPublish);
} catch (e) {
this.queue.set(id, { ...params, attempt: 1 });
this.queue.set(id, { request, opts, attempt: 1 });
this.logger.warn(e, (e as Error)?.message);
}
});
Expand All @@ -128,6 +129,87 @@ export class Publisher extends IPublisher {
}
};

public publishCustom: IPublisher["publishCustom"] = async (params) => {
this.logger.debug(`Publishing custom payload`);
this.logger.trace({ type: "method", method: "publishCustom", params });

const { payload, opts = {} } = params;
const { attestation, tvf, publishMethod, prompt, tag, ttl = FIVE_MINUTES } = opts;

const id = opts.id || (getBigIntRpcId().toString() as any);
const api = getRelayProtocolApi(getRelayProtocolName().protocol);
const method = publishMethod || api.publish;
const request: RequestArguments<RelayJsonRpc.PublishParams> = {
id,
method,
params: {
...payload,
ttl,
prompt,
tag,
attestation,
...tvf,
},
};
console.log("publishCustom request", request);
const failedPublishMessage = `Failed to publish custom payload, please try again. id:${id} tag:${tag}`;
console.log("publish params", opts);
try {
if (isUndefined(request.params?.prompt)) delete request.params?.prompt;
if (isUndefined(request.params?.tag)) delete request.params?.tag;

/**
* attempt to publish the payload for <initialPublishTimeout> seconds,
* if the publish fails, add the payload to the queue and it will be retried on every pulse
* until it is successfully published or <publishTimeout> seconds have passed
*/
const publishPromise = new Promise<void>(async (resolve) => {
const onPublish = ({ id }: { id: string }) => {
if (request.id?.toString() === id.toString()) {
this.removeRequestFromQueue(id);
this.relayer.events.removeListener(RELAYER_EVENTS.publish, onPublish);
resolve();
}
};
this.relayer.events.on(RELAYER_EVENTS.publish, onPublish);
const initialPublish = createExpiringPromise(
new Promise((resolve, reject) => {
this.rpcPublish(request, opts)
.then(resolve)
.catch((e) => {
this.logger.warn(e, e?.message);
reject(e);
});
}),
this.initialPublishTimeout,
`Failed initial custom payload publish, retrying.... method:${method} id:${id} tag:${tag}`,
);
try {
await initialPublish;
this.events.removeListener(RELAYER_EVENTS.publish, onPublish);
} catch (e) {
this.queue.set(id, { request, opts, attempt: 1 });
this.logger.warn(e, (e as Error)?.message);
}
});
this.logger.trace({
type: "method",
method: "publish",
params: { id, payload, opts },
});

await createExpiringPromise(publishPromise, this.publishTimeout, failedPublishMessage);
} catch (e) {
this.logger.debug(`Failed to Publish Payload`);
this.logger.error(e as any);
if (opts?.internal?.throwOnFailedPublish) {
throw e;
}
} finally {
this.queue.delete(id);
}
};

public on: IPublisher["on"] = (event, listener) => {
this.events.on(event, listener);
};
Expand All @@ -146,46 +228,14 @@ export class Publisher extends IPublisher {

// ---------- Private ----------------------------------------------- //

private async rpcPublish(params: {
topic: string;
message: string;
ttl?: number;
prompt?: boolean;
tag?: number;
id?: number;
attestation?: string;
tvf?: RelayerTypes.ITVF;
}) {
const {
topic,
message,
ttl = PUBLISHER_DEFAULT_TTL,
prompt,
tag,
id,
attestation,
tvf,
} = params;
const api = getRelayProtocolApi(getRelayProtocolName().protocol);
const request: RequestArguments<RelayJsonRpc.PublishParams> = {
method: api.publish,
params: {
topic,
message,
ttl,
prompt,
tag,
attestation,
...tvf,
},
id,
};
if (isUndefined(request.params?.prompt)) delete request.params?.prompt;
if (isUndefined(request.params?.tag)) delete request.params?.tag;
private async rpcPublish(request: RequestArguments, opts?: RelayerTypes.PublishOptions) {
console.log("rpcPublish params", request, globalThis.CoreId);
this.logger.debug(`Outgoing Relay Payload`);
this.logger.trace({ type: "message", direction: "outgoing", request });
const result = await this.relayer.request(request);
this.relayer.events.emit(RELAYER_EVENTS.publish, params);
console.log("rpcPublish result", result);

this.relayer.events.emit(RELAYER_EVENTS.publish, { ...request, ...opts });
this.logger.debug(`Successfully Published Payload`);
return result;
}
Expand All @@ -198,23 +248,12 @@ export class Publisher extends IPublisher {
this.queue.forEach(async (params, id) => {
const attempt = params.attempt + 1;
this.queue.set(id, { ...params, attempt });
const { topic, message, opts, attestation } = params;
this.logger.warn(
{},
`Publisher: queue->publishing: ${params.opts.id}, tag: ${params.opts.tag}, attempt: ${attempt}`,
`Publisher: queue->publishing: ${params.request.id}, tag: ${params.request.params?.tag}, attempt: ${attempt}`,
);
await this.rpcPublish({
...params,
topic,
message,
ttl: opts.ttl,
prompt: opts.prompt,
tag: opts.tag,
id: opts.id,
attestation,
tvf: opts.tvf,
});
this.logger.warn({}, `Publisher: queue->published: ${params.opts.id}`);
await this.rpcPublish(params.request, params.opts);
this.logger.warn({}, `Publisher: queue->published: ${params.request.id}`);
});
}

Expand Down
12 changes: 9 additions & 3 deletions packages/core/src/controllers/relayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ export class Relayer extends IRelayer {
this.subscriber = new Subscriber(this, this.logger);
this.publisher = new Publisher(this, this.logger);

this.relayUrl = opts?.relayUrl || RELAYER_DEFAULT_RELAY_URL;
this.projectId = opts.projectId;
this.relayUrl = RELAYER_DEFAULT_RELAY_URL;
this.projectId = "47a263e9e957d954353cb970f024e1d3";

if (isAndroid()) {
this.packageName = getAppId();
Expand Down Expand Up @@ -173,6 +173,11 @@ export class Relayer extends IRelayer {
);
}

public async publishCustom(params: { payload: any; opts?: RelayerTypes.PublishOptions }) {
this.isInitialized();
await this.publisher.publishCustom(params);
}

public async subscribe(topic: string, opts?: RelayerTypes.SubscribeOptions) {
this.isInitialized();
if (!opts?.transportType || opts?.transportType === "relay") {
Expand Down Expand Up @@ -281,7 +286,8 @@ export class Relayer extends IRelayer {
async transportOpen(relayUrl?: string) {
if (!this.subscriber.hasAnyTopics) {
this.logger.warn(
"Starting WS connection skipped because the client has no topics to work with.",
"Starting WS connection skipped because the client has no topics to work with." +
globalThis.CoreId,
);
return;
}
Expand Down
Loading
Loading