@walletconnect/client
Client for WalletConnect Protocol
Description
This library provides a Standalone Client for WalletConnect 2.0 Protocol for both Dapps and Wallets. Integration will differ from the perspective of each client as the Proposer and Responder, respectively. It's compatible with NodeJS, Browser and React-Native applications (NodeJS modules required to be polyfilled for React-Native)
Install
yarn add @walletconnect/client
npm install --save @walletconnect/client
Create Session
This quick start example will describe how an integration should be followed for both Dapps and Wallets respectively
Dapps
- Initiate your WalletConnect client with the relay server
import WalletConnectClient from "@walletconnect/client";
const client = await WalletConnectClient.init({ relayProvider: "wss://staging.walletconnect.org" });
- Subscribe to connection proposal event for sharing URI
import { CLIENT_EVENTS } from "@walletconnect/client";
import { ConnectionTypes } from "@walletconnect/types";
client.on(CLIENT_EVENTS.connection.proposal, async (proposal: ConnectionTypes.Proposal) => {
const { uri } = proposal.signal.params;
});
- Connect application and specify session permissions
const session = await client.connect({
metadata: {
name: "Example Dapp",
description: "Example Dapp",
url: "#",
icons: ["https://walletconnect.org/walletconnect-logo.png"],
},
permissions: {
blockchain: {
chainIds: ["eip155:1"],
},
jsonrpc: {
methods: ["eth_sendTransaction", "personal_sign", "eth_signTypedData"],
},
},
});
Wallets
- Initiate your WalletConnect client with the relay server
import WalletConnectClient from "@walletconnect/client";
const client = await WalletConnectClient.init({ relayProvider: "wss://staging.walletconnect.org" });
- Subscribe to session proposal event for user approval and session created when successful
import { CLIENT_EVENTS } from "@walletconnect/client";
import { SessionTypes } from "@walletconnect/types";
client.on(CLIENT_EVENTS.session.proposal, async (proposal: SessionTypes.Proposal) => {
const { proposer, permissions } = proposal;
const { metadata } = proposer;
let approved: boolean;
handleSessionUserApproval(approved, proposal);
});
client.on(CLIENT_EVENTS.session.created, async (session: SessionTypes.Created) => {
});
- Establish connection with shared URI from dapp
client.tether({ uri });
- Handle user approval for proposed session
function handleSessionUserApproval(approved: boolean, proposal: SessionTypes.Proposal) {
if (userApproved) {
const response: SessionTypes.Response = {
metadata: {
name: "Test Wallet",
description: "Test Wallet",
url: "#",
icons: ["https://walletconnect.org/walletconnect-logo.png"],
},
state: {
accountIds: ["0x1d85568eEAbad713fBB5293B45ea066e552A90De@eip155:1"],
},
}
await client.approve({ proposal, response });
} else {
await client.reject({ proposal });
}
}
JSON-RPC Payloads
Dapps
Once the session has been succesfull then you can start making JSON-RPC requests to be approved and signed by the wallet
const result = await client.request({
topic: session.topic,
chainId: "eip155:1",
request: {
id: 1,
jsonrpc: "2.0",
method: "personal_sign",
params: [
"0x1d85568eEAbad713fBB5293B45ea066e552A90De",
"0x7468697320697320612074657374206d65737361676520746f206265207369676e6564",
],
},
});
Wallets
Given that session has settled succesfully since user approved the session on the wallet side, then the Wallet should subscribe to session payload events on the client
import { CLIENT_EVENTS } from "@walletconnect/client";
import { SessionTypes } from "@walletconnect/types";
import { JsonRpcResponse } from "@json-rpc-tools/utils";
client.on(CLIENT_EVENTS.session.payload, async (payloadEvent: SessionTypes.PayloadEvent) => {
const { topic, payload } = payloadEvent;
const session = await client.session.get(payloadEvent.topic);
const { metadata } = session.peer;
let result: any;
const response = approved
? {
topic,
response: {
id: payload.id,
jsonrpc: "2.0",
result,
},
}
: {
topic,
response: {
id: payload.id,
jsonrpc: "2.0",
error: {
code: -32000,
message: "User rejected JSON-RPC request",
},
},
};
await client.respond(response);
});
API
export interface ClientOptions {
logger?: string | Logger;
storage?: IKeyValueStorage;
relayProvider?: string | IJsonRpcProvider;
overrideContext?: string;
}
export abstract class IClient extends IEvents {
public readonly protocol = "wc";
public readonly version = 2;
public abstract logger: Logger;
public abstract relay: IRelay;
public abstract storage: IKeyValueStorage;
public abstract connection: IConnection;
public abstract session: ISession;
constructor(opts?: ClientOptions) {
super();
}
public abstract connect(params: ClientTypes.ConnectParams): Promise<SessionTypes.Settled>;
public abstract tether(params: ClientTypes.TetherParams): Promise<void>;
public abstract approve(params: ClientTypes.ApproveParams): Promise<SessionTypes.Settled>;
public abstract reject(params: ClientTypes.RejectParams): Promise<void>;
public abstract update(params: ClientTypes.UpdateParams): Promise<void>;
public abstract notify(params: ClientTypes.NotifyParams): Promise<void>;
public abstract request(params: ClientTypes.RequestParams): Promise<any>;
public abstract respond(params: ClientTypes.RespondParams): Promise<void>;
public abstract disconnect(params: ClientTypes.DisconnectParams): Promise<void>;
}
export declare namespace ClientTypes {
export interface ConnectParams {
metadata: SessionTypes.Metadata;
permissions: SessionTypes.BasePermissions;
relay?: RelayTypes.ProtocolOptions;
connection?: SignalTypes.ParamsConnection;
}
export interface TetherParams {
uri: string;
}
export interface ApproveParams {
proposal: SessionTypes.Proposal;
response: SessionTypes.Response;
}
export interface RejectParams {
proposal: SessionTypes.Proposal;
}
export type UpdateParams = SessionTypes.UpdateParams;
export type NotifyParams = SessionTypes.NotifyParams;
export interface RequestParams {
topic: string;
request: JsonRpcRequest;
chainId?: string;
}
export interface RespondParams {
topic: string;
response: JsonRpcResponse;
}
export interface DisconnectParams {
topic: string;
reason: string;
}
}
License
LGPL-3.0