Skip to content

Commit

Permalink
feat: add permissions methods
Browse files Browse the repository at this point in the history
  • Loading branch information
krzysu committed Oct 28, 2024
1 parent ebae44d commit 413e88c
Show file tree
Hide file tree
Showing 6 changed files with 262 additions and 28 deletions.
57 changes: 30 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
This Web3.js plugin adds support for the following wallet-related RPC methods:

- [wallet_addEthereumChain (EIP-3085)](https://eips.ethereum.org/EIPS/eip-3085)
- [wallet_updateEthereumChain (EIP-2015)](https://eips.ethereum.org/EIPS/eip-2015)
- [wallet_switchEthereumChain (EIP-3326)](https://eips.ethereum.org/EIPS/eip-3326)
- [wallet_getOwnedAssets (EIP-2256)](https://eips.ethereum.org/EIPS/eip-2256)
- [wallet_watchAsset (EIP-747)](https://eips.ethereum.org/EIPS/eip-747)

Not implemented yet:

- [wallet_requestPermissions (EIP-2255)](https://eips.ethereum.org/EIPS/eip-2255)
- [wallet_getPermissions (EIP-2255)](https://eips.ethereum.org/EIPS/eip-2255)
- [wallet_revokePermissions](https://docs.metamask.io/wallet/reference/json-rpc-methods/wallet_revokepermissions/)

Experimental:

- [wallet_updateEthereumChain (EIP-2015)](https://eips.ethereum.org/EIPS/eip-2015)
- [wallet_getOwnedAssets (EIP-2256)](https://eips.ethereum.org/EIPS/eip-2256)

## Installation

Expand Down Expand Up @@ -62,6 +63,30 @@ await web3.walletRpc.addEthereumChain({
});
```

#### switchEthereumChain

Invokes the `wallet_switchEthereumChain` method as defined in [EIP-3326](https://eips.ethereum.org/EIPS/eip-3326).

```typescript
await web3.walletRpc.switchEthereumChain({ chainId: 5000 });
```

#### watchAsset

Invokes the `wallet_watchAsset` method as defined in [EIP-747](https://eips.ethereum.org/EIPS/eip-747).

```typescript
await web3.walletRpc.watchAsset({
type: "ERC20",
options: {
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
symbol: "USDC",
},
});
```

### Experimental methods

#### updateEthereumChain

Invokes the `wallet_updateEthereumChain` method as defined in [EIP-2015](https://eips.ethereum.org/EIPS/eip-2015).
Expand All @@ -80,14 +105,6 @@ await web3.walletRpc.updateEthereumChain({
});
```

#### switchEthereumChain

Invokes the `wallet_switchEthereumChain` method as defined in [EIP-3326](https://eips.ethereum.org/EIPS/eip-3326).

```typescript
await web3.walletRpc.switchEthereumChain({ chainId: 5000 });
```

#### getOwnedAssets

Invokes the `wallet_getOwnedAssets` method as defined in [EIP-2256](https://eips.ethereum.org/EIPS/eip-2256).
Expand All @@ -98,20 +115,6 @@ const ownedAssets = await web3.walletRpc.getOwnedAssets({
});
```

#### watchAsset

Invokes the `wallet_watchAsset` method as defined in [EIP-747](https://eips.ethereum.org/EIPS/eip-747).

```typescript
await web3.walletRpc.watchAsset({
type: "ERC20",
options: {
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
symbol: "USDC",
},
});
```

## Contributing

We welcome pull requests! For major changes, please open an issue first to discuss the proposed modifications.
Expand Down
91 changes: 90 additions & 1 deletion packages/web3-plugin-wallet-rpc/src/WalletRpcPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import type {
AddEthereumChainRequest,
GetOwnedAssetsRequest,
OwnedAsset,
Permission,
PermissionRequest,
UpdateEthereumChainRequest,
WatchAssetRequest,
} from "./types";
Expand All @@ -16,6 +18,9 @@ type WalletRpcApi = {
wallet_switchEthereumChain: (chainId: Numbers) => void;
wallet_getOwnedAssets: (param: GetOwnedAssetsRequest) => OwnedAsset[];
wallet_watchAsset: (param: WatchAssetRequest) => boolean;
wallet_requestPermissions: (param: PermissionRequest) => Permission[];
wallet_getPermissions: () => Permission[];
wallet_revokePermissions: (param: PermissionRequest) => void;
};

/**
Expand Down Expand Up @@ -46,6 +51,20 @@ export class WalletRpcPlugin extends Web3PluginBase<WalletRpcApi> {
*
* @param param - Details of the chain to add
* @returns a Promise that resolves if the request is successful
*
* @example
* await web3.walletRpc.addEthereumChain({
* chainId: 5000,
* blockExplorerUrls: ["https://mantlescan.xyz"],
* chainName: "Mantle",
* iconUrls: ["https://icons.llamao.fi/icons/chains/rsz_mantle.jpg"],
* nativeCurrency: {
* name: "Mantle",
* symbol: "MNT",
* decimals: 18,
* },
* rpcUrls: ["https://rpc.mantle.xyz"],
* });
*/
public async addEthereumChain(param: AddEthereumChainRequest): Promise<void> {
return this.requestManager.send({
Expand All @@ -66,6 +85,7 @@ export class WalletRpcPlugin extends Web3PluginBase<WalletRpcApi> {
*
* @param param - Details of the chain to switch to and possibly add
* @returns a Promise that resolves if the request is successful
* @experimental
*/
public async updateEthereumChain(
param: UpdateEthereumChainRequest,
Expand All @@ -88,6 +108,9 @@ export class WalletRpcPlugin extends Web3PluginBase<WalletRpcApi> {
*
* @param chainId - Chain ID of the chain to switch to
* @returns a Promise that resolves if the request is successful
*
* @example
* await web3.walletRpc.switchEthereumChain({ chainId: 5000 });
*/
public async switchEthereumChain(chainId: Numbers): Promise<void> {
return this.requestManager.send({
Expand All @@ -107,6 +130,7 @@ export class WalletRpcPlugin extends Web3PluginBase<WalletRpcApi> {
*
* @param param - Details of the request for owned assets
* @returns a Promise that resolves to a list of owned assets
* @experimental
*/
public async getOwnedAssets(
param: GetOwnedAssetsRequest,
Expand All @@ -133,16 +157,81 @@ export class WalletRpcPlugin extends Web3PluginBase<WalletRpcApi> {
*
* @param param - Details of the asset to watch
* @returns a Promise that resolves to `true` if the request is successful
*
* @example
* await web3.walletRpc.watchAsset({
* type: "ERC20",
* options: {
* address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
* symbol: "USDC",
* },
* });
*/
public async watchAsset(param: WatchAssetRequest): Promise<boolean> {
return this.requestManager.send({
method: "wallet_watchAsset",
params: [param],
});
}

/**
* Request permissions for a dApp.
*
* See [EIP-2255](https://eips.ethereum.org/EIPS/eip-2255) for more details.
*
* @param param - Details of the permission request
* @returns a Promise that resolves to an array of granted permissions
*
* @example
* const permissions = await web3.walletRpc.requestPermissions({
* eth_accounts: {}
* });
*/
public async requestPermissions(
param: PermissionRequest,
): Promise<Permission[]> {
return this.requestManager.send({
method: "wallet_requestPermissions",
params: [param],
});
}

/**
* Retrieve the list of permissions granted to the dApp.
*
* See [EIP-2255](https://eips.ethereum.org/EIPS/eip-2255) for more details.
*
* @returns a Promise that resolves to an array of granted permissions
*
* @example
* const permissions = await web3.walletRpc.getPermissions();
*/
public async getPermissions(): Promise<Permission[]> {
return this.requestManager.send({
method: "wallet_getPermissions",
params: [],
});
}

/**
* Revoke permissions granted to the dApp.
*
* @param param - Details of the permissions to revoke
* @returns a Promise that resolves if the request is successful
*
* @example
* await web3.walletRpc.revokePermissions({
* eth_accounts: {}
* });
*/
public async revokePermissions(param: PermissionRequest): Promise<void> {
return this.requestManager.send({
method: "wallet_revokePermissions",
params: [param],
});
}
}

// Module Augmentation
declare module "web3" {
interface Web3Context {
walletRpc: WalletRpcPlugin;
Expand Down
56 changes: 56 additions & 0 deletions packages/web3-plugin-wallet-rpc/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,59 @@ export type WatchAssetRequest = {
image?: string;
};
};

/**
* Request or revoke permissions.
*
* See [EIP-2255](https://eips.ethereum.org/EIPS/eip-2255) for more details.
*/
export type PermissionRequest = Record<string, Object>;

/**
* Specific restrictions applied to the permitted method
*
* See [EIP-2255](https://eips.ethereum.org/EIPS/eip-2255) for more details.
*/
export type Caveat = {
/**
* The type of the Caveat.
*/
type: string;

/**
* An arbitrary JSON value. The value of a Caveat is only meaningful in the context of the type of the Caveat.
*/
value: any;
};

/**
* Permission granted to a dApp.
*
* See [EIP-2255](https://eips.ethereum.org/EIPS/eip-2255) for more details.
*/
export type Permission = {
/**
* The permission ID.
*/
id: string;

/**
* A URI of the dapp being granted this permission.
*/
invoker: string;

/**
* The method that is being permitted (e.g. eth_accounts).
*/
parentCapability: string;

/**
* A list of restrictions applied to the method.
*/
caveats: Caveat[];

/**
* The date is the timestamp of the request, in Unix time, and is optional.
*/
date?: number;
};
26 changes: 26 additions & 0 deletions packages/web3-plugin-wallet-rpc/test/wallet_getPermissions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Web3 } from "web3";

import { WalletRpcPlugin } from "../src";

describe("WalletRpcPlugin", () => {
describe("wallet_getPermissions", () => {
const web3 = new Web3("http://127.0.0.1:8545");
web3.registerPlugin(new WalletRpcPlugin());

const requestManagerSendSpy = jest.fn();
web3.requestManager.send = requestManagerSendSpy;

afterEach(() => {
requestManagerSendSpy.mockClear();
});

it("should call the method with expected params", async () => {
await web3.walletRpc.getPermissions();

expect(requestManagerSendSpy).toHaveBeenCalledWith({
method: "wallet_getPermissions",
params: [],
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Web3 } from "web3";

import { WalletRpcPlugin } from "../src";

describe("WalletRpcPlugin", () => {
describe("wallet_requestPermissions", () => {
const web3 = new Web3("http://127.0.0.1:8545");
web3.registerPlugin(new WalletRpcPlugin());

const requestManagerSendSpy = jest.fn();
web3.requestManager.send = requestManagerSendSpy;

afterEach(() => {
requestManagerSendSpy.mockClear();
});

it("should call the method with expected params", async () => {
const request = {
eth_accounts: {},
};

await web3.walletRpc.requestPermissions(request);

expect(requestManagerSendSpy).toHaveBeenCalledWith({
method: "wallet_requestPermissions",
params: [request],
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Web3 } from "web3";

import { WalletRpcPlugin } from "../src";

describe("WalletRpcPlugin", () => {
describe("wallet_revokePermissions", () => {
const web3 = new Web3("http://127.0.0.1:8545");
web3.registerPlugin(new WalletRpcPlugin());

const requestManagerSendSpy = jest.fn();
web3.requestManager.send = requestManagerSendSpy;

afterEach(() => {
requestManagerSendSpy.mockClear();
});

it("should call the method with expected params", async () => {
const request = {
eth_accounts: {},
};

await web3.walletRpc.revokePermissions(request);

expect(requestManagerSendSpy).toHaveBeenCalledWith({
method: "wallet_revokePermissions",
params: [request],
});
});
});
});

0 comments on commit 413e88c

Please sign in to comment.