Skip to content
3 changes: 2 additions & 1 deletion CAIPs/caip-282.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ interface WalletAnnounceRequestParams {
name: string;
icon: string;
rdns: string;
targets?: { type: string, value: any }[],
scopes?: AuthorizationScopes;
}
```
Expand All @@ -68,7 +69,7 @@ Whenever a new Wallet Provider is discovered the Blockchain Library would index

The parameters `name` and `icon` are used to display to the user to be easily recognizable while the `rdns` and `uuid` are only used internally for de-duping while they must always be unique, the `rdns` will always be the same but `uuid` is ephemeral per browser session.

The only optional parameter is `scopes` which is defined by CAIP-217 authorization specs that enables early discoverability and filtering of wallets based on RPC methods, notifications, documents and endpoints but also optional discovery of supported chains and even accounts.
The optional parameters are `scopes`, which is defined by [CAIP-217] authorization specs that enables early discoverability and filtering of wallets based on RPC methods, notifications, documents and endpoints but also optional discovery of supported chains and even accounts, and `targets`, which accepts [CAIP-341] Extension ID as a valid target type for establishing connections with browser extension wallets via the [CAIP-294] `wallet_announce` wallet discovery event.

```typescript
// Defined by CAIP-217
Expand Down
43 changes: 29 additions & 14 deletions CAIPs/caip-294.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ The `walletData` object MUST include the following properties:

Additionally, the `walletData` object MAY include the following optional properties:

- `extensionId`: The canonical extension ID of the wallet provider for the active browser.
- `targets`: An array of objects, with an object containing `type: "caip341"` and `value: <extension_id>` used to connect to wallets using `externally_connectable`. Important to note here that other CAIPs can extend this, and [CAIP-341][caip-341] is an example of a valid target type for this use case.
- `scopes`: An object defining the authorization scopes supported by the wallet, as specified in CAIP-217.

```typescript
Expand All @@ -148,12 +148,8 @@ interface WalletData {
name: string;
icon: string;
rdns: string;

// Optional properties
target?: {
origin?: string;
extensionId?: string;
}
targets?: { type: string, value: any }[],
scopes?: Caip217AuthorizationScopes;
}
```
Expand All @@ -166,7 +162,22 @@ const walletData = {
name: "Example Wallet",
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",
rdns: "com.example.wallet",
extensionId: "abcdefghijklmnopqrstuvwxyz",
targets: [
{
type: "caip341",
value: "abcdefghijklmnopqrstuvwxyz"
},
{
type: "caip315",
value: true
},
{
type: "caip316",
value: {
somethingElse: "hello"
}
},
]
scopes: {
"eip155:1": {
methods: ["eth_signTransaction", "eth_sendTransaction"],
Expand All @@ -176,20 +187,20 @@ const walletData = {
}
```

This `walletData` type is is a superset of `WalletAnnounceRequestParams` type described in the [CAIP-282][caip-282] standard, adding the optional `extensionId` property as it is only relevant for browser extension based wallets.
This `walletData` type is a superset of `WalletAnnounceRequestParams` type described in the [CAIP-282][caip-282] standard, adding the optional `targets` property with the object defining `extensionId`, as it is only relevant for browser extension based wallets.

### ExtensionId
### Targets

When the `extensionId` is included in the `walletData` object, it indicates that the wallet supports communication via the browser's `externally_connectable` API. In this case:
When a `targets` property with the array containing an object with [`type: 'caip341'`][caip-341] is included in the `walletData` object, it indicates that the wallet expects communication via the browser's [`externally_connectable` API][externally_connectable]. In this case:

1. The dapp MUST use the `extensionId` to establish a connection with the wallet using the `externally_connectable` browser API.
1. The dapp MUST use the `targets.find(({ type }) => type === "caip314").value` (an [`extensionId`][externally_connectable]) to establish a connection with the wallet using the `externally_connectable` browser API.
2. All subsequent communication with the wallet (the "session") SHOULD be conducted over the `externally_connectable` API using `runtime.connect()` and `runtime.sendMessage()`.
3. The dapp MUST NOT use the injected provider for communication when `extensionId` is present.
3. The dapp MUST NOT use the injected provider for communication when `targets` with [CAIP-341](https://github.com/ChainAgnostic/CAIPs/blob/656551f800843b92243fb08ca6c24e805ad149a3/CAIPs/caip-341.md) type is present.

Example of establishing a connection and sending a message:

```javascript
const port = chrome.runtime.connect(walletData.extensionId);
const port = chrome.runtime.connect(walletData.targets.value);

port.onMessage.addListener((message) => {
// Handle incoming messages
Expand All @@ -205,7 +216,7 @@ port.postMessage({
});
```

If the `extensionId` is not present in the `walletData` object, the dapp SHOULD assume that communication will occur through the traditional injected provider method.
If the `targets` object with [CAIP-341](https://github.com/ChainAgnostic/CAIPs/blob/656551f800843b92243fb08ca6c24e805ad149a3/CAIPs/caip-341.md) type is not present in the `walletData` object, the dapp SHOULD assume that communication will occur through the traditional injected provider method.

#### Handshake

Expand Down Expand Up @@ -500,11 +511,15 @@ TODO
- [CAIP-27][caip-27] - Blockchain ID Specification
- [CAIP-25][caip-25] - Blockchain ID Specification
- [CAIP-282][caip-282] - Browser Wallet Discovery Interface
- [CAIP-341][caip-341] - Extension ID Target Type Specification
- [externally_connectable][externally_connectable] - Chrome's `externally_connectable` browser API documentation

[eip-6963]: https://eips.ethereum.org/EIPS/eip-6963
[caip-27]: https://chainagnostic.org/CAIPs/caip-27
[caip-25]: https://chainagnostic.org/CAIPs/caip-25
[caip-282]: https://chainagnostic.org/CAIPs/caip-282
[caip-341]: https://github.com/ChainAgnostic/CAIPs/blob/656551f800843b92243fb08ca6c24e805ad149a3/CAIPs/caip-341.md
[externally_connectable]: https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable

## Copyright

Expand Down
26 changes: 18 additions & 8 deletions CAIPs/caip-295.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ This provides the foundation for any Wallet Provider to interface with a Decentr

Different loading times can be affected by multiple factors, which makes it non-deterministic to publish and listen to messages from different sources within the browser.

#### Target Origin

TODO Make Proposal For Target Origin As Valid Target Type For Wallet Data.

#### Discovery

Both Wallet Providers and blockchain libraries must listen to incoming messages that might be published after their initialization. Additionally both Wallet Providers and blockchain libraries must publish a message to both announce themselves and their intent to connect, respectively.
Expand All @@ -56,7 +60,10 @@ Here is the expected logic from the Blockchain Library:
```typescript
interface WalletMapEntry {
data: WalletAnnounceRequestParams;
targetOrigin: string;
targets: {
type: <caip-id-for-target-origin>;
value: <target-origin>
}[]
}

const wallets: Record<string, WalletMapEntry> = {}
Expand All @@ -67,7 +74,7 @@ window.addEventListener("message", (event) => {
// when an announce message was received then the library can index it by uuid
wallets[event.data.params.uuid] = {
params: event.data.params,
targetOrigin: event.targetOrigin
targetOrigin: event.target.value
}
}
});
Expand Down Expand Up @@ -158,7 +165,10 @@ Logic from the Blockchain Library:
// also by posting a prompt message
interface WalletMapEntry {
data: WalletAnnounceRequestParams;
targetOrigin: string;
targets: {
type: <caip-id-for-target-origin>;
value: <target-origin>
}[]
}

const wallets: Record<string, WalletMapEntry> = {}
Expand All @@ -168,7 +178,7 @@ window.addEventListener("message", (event) => {
// when an announce message was received then the library can index it by uuid
wallets[event.data.params.uuid] = {
params: event.data.params,
targetOrigin: event.targetOrigin
targetOrigin: event.targets.find(({ type }) => type === "caip295")?.value
}
}
});
Expand Down Expand Up @@ -208,7 +218,7 @@ const sessionRequest = {
let sessionResult = {}

window.addEventListener("message", (event) => {
if (event.targetOrigin !== wallets[selected_uuid].targetOrigin) return;
if (event.targets.find(({ type }) => type === "caip295")?.value !== wallets[selected_uuid].targetOrigin) return;
if (event.data.id === sessionRequest.id) {
// Get JSON-RPC response
if (event.data.error) {
Expand Down Expand Up @@ -247,7 +257,7 @@ const signingRequest = {
let signingResult = {}

window.addEventListener("message", (event) => {
if (event.targetOrigin !== wallets[selected_uuid].targetOrigin) return;
if (event.targets.find(({ type }) => type === "caip295")?.value !== wallets[selected_uuid].targetOrigin) return;
if (event.data.id === signingRequest.id) {
// Get JSON-RPC response
if (event.data.error) {
Expand Down Expand Up @@ -309,7 +319,7 @@ window.addEventListener("message", (event) => {
if (checkSupportedScopes(event.data.params)) {
// prompt user to approve session
// persist the targetOrigin for sessionRequest
sessionOrigin = event.targetOrigin
sessionOrigin = event.targets.find(({ type }) => type === "caip295")?.value
}
}
});
Expand Down Expand Up @@ -344,7 +354,7 @@ window.postMessage(sessionResponse, sessionOrigin);
let signingRequest = {}

window.addEventListener("message", (event) => {
if (event.targetOrigin !== sessionOrigin) return;
if (event.targets.find(({ type }) => type === "caip295")?.value !== sessionOrigin) return;
if (event.data.method === "wallet_createSession" && event.data.params.sessionId === walletData.uuid) {
signingRequest = event.data.params
}
Expand Down