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

SIP-29 Improvements #155

Merged
merged 13 commits into from
Dec 6, 2024
198 changes: 125 additions & 73 deletions SIPS/sip-29.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,85 +35,147 @@ in uppercase in this document are to be interpreted as described in [RFC
2. Any time an asset needs to be identified, it MUST use the [CAIP-19][caip-19]
representation.

### Snap Assets API
### Snap Manifest

This SIP introduces a new permission named `endowment:assets`.
This permission grants a Snap the ability to provide asset information to the client.

This permission is specified as follows in `snap.manifest.json` files:

```json
{
"initialPermissions": {
"endowment:assets": {
"chains": [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we allow namespaces as well? And we should probably name it scopes to be aligned with SIP-26, CAIP-25/27.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's your thinking for allowing namespaces ? I would prefer this to be granular and to have to define reference supported rather than defining namespaces that would probably introduce calls for reference that are not supported

"bip122:000000000019d6689c085ae165831e93"
]
}
}
}
```

`chains` - A non-empty array of CAIP-2 chain IDs that the snap supports. This field is useful for a client in order to avoid unnecessary overhead.

### Snap Implementation

Two methods are defined in the Snap Assets API:

#### Get Token Description
Any Snap that wishes to provide asset information **MUST** implement the following API:

#### Get Asset Description

```typescript
import { OnAssetDescriptionHandler } from "@metamask/snaps-sdk";

export const onAssetDescription: OnAssetDescriptionHandler = async ({
GuillaumeRx marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing this will be covered in another doc, but I'm curious how data is added to this list provided by the caller. How are assets discovered originally?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is covered by the kering API with the listAccountAssets method IIRC @danroc can provide more details about it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then the snap uses any API that provides asset metadata to create its token description

assets
}) => {
const description = /* Get description */;
return { description };
};
```

The type for an `onAssetDescription` handler function’s arguments is:

```typescript
interface OnAssetDescriptionArgs {
assets: Caip19AssetType[];
}
```
The type for an `onAssetDescription` handler function’s return value is:

```typescript
// Represents a token unit.
type TokenUnit = {
// Human-friendly name of the token unit.
// {
// name: 'Ether',
// ticker: 'ETH',
// isNative: true,
// iconBase64: 'data:image/png;base64,...',
// units: [
// {
// name: 'Ether',
// ticker: 'ETH',
// decimals: 18
// },
// {
// name: 'Gwei',
// ticker: 'Gwei',
// decimals: 9
// },
// {
// name: 'wei',
// ticker: 'wei',
// decimals: 0
// }
// ]
// }

// Represents a asset unit.
type AssetUnit = {
// Human-friendly name of the asset unit.
name: string;

// Ticker of the token unit.
// Ticker of the asset unit.
ticker: string;

// Number of decimals of the token unit.
// Number of decimals of the asset unit.
decimals: number;
};

// Token description.
type TokenDescription = {
// Human-friendly name of the token.
// Asset description.
type AssetDescription = {
// The CAIP-19 ID of the asset.
id: Caip19AssetType;

// Human-friendly name of the asset.
name: string;

// Ticker of the token.
// Ticker of the asset.
ticker: string;

// Whether the token is native to the chain.
// Whether the asset is native to the chain.
isNative: boolean;

// Base64 representation of the token icon.
// Base64 representation of the asset icon.
iconBase64: string;

// List of token units.
units: TokenUnit[];
// List of asset units.
units: AssetUnit[];
};

// Returns the description of a non-fungible token. This description can then
// be used by the client to display relevant information about the token.
//
// @example
// ```typescript
// const tokenDescription = await getTokenDescription('eip155:1/slip44:60');
//
// // Returns:
// // {
// // name: 'Ether',
// // ticker: 'ETH',
// // isNative: true,
// // iconBase64: 'data:image/png;base64,...',
// // units: [
// // {
// // name: 'Ether',
// // ticker: 'ETH',
// // decimals: 18
// // },
// // {
// // name: 'Gwei',
// // ticker: 'Gwei',
// // decimals: 9
// // },
// // {
// // name: 'wei',
// // ticker: 'wei',
// // decimals: 0
// // }
// // ]
// // }
// ```
function getTokenDescription(token: Caip19AssetType): TokenDescription;

type OnAssetDescriptionReturn = {
description: Record<Caip19AssetType, AssetDescription>;
};
```

#### Get Token Conversion Rate
#### Get Asset Conversion Rate

```typescript
import { OnAssetConversionHandler } from "@metamask/snaps-sdk";

export const onAssetConversion: OnAssetConversionHandler = async ({
GuillaumeRx marked this conversation as resolved.
Show resolved Hide resolved
from,
to
}) => {
const conversionRate = /* Get conversion rate */;
return { conversionRate };
};
```
The type for an `onAssetDescription` handler function’s arguments is:

```typescript
type TokenConversionRate = {
// The rate of conversion from the source token to the target token. It
// means that 1 unit of the `from` token should be converted to this amount
// of the `to` token.
interface OnAssetConversionArgs {
from: Caip19AssetType[];
to: Caip19AssetType;
GuillaumeRx marked this conversation as resolved.
Show resolved Hide resolved
}
```
The type for an `onAssetDescription` handler function’s return value is:

```typescript
type AssetConversionRate = {
// The rate of conversion from the source asset to the target asset. It
// means that 1 unit of the `from` asset should be converted to this amount
// of the `to` asset.
rate: string;

// The UNIX timestamp of when the conversion rate was last updated.
Expand All @@ -123,26 +185,16 @@ type TokenConversionRate = {
expirationTime: number;
};

// Returns the conversion rate between two assets (tokens or fiat).
//
// @example
// ```typescript
// const conversionRate = await getTokenConversionRate(
// 'eip155:1/slip44:60',
// 'eip155:1/erc20:0x6b175474e89094c44da98b954eedeac495271d0f'
// );
//
// // Returns:
// // {
// // rate: '3906.38',
// // conversionTime: 1733389786,
// // expirationTime: 1733389816,
// // }
// ```
function getTokenConversionRate(
from: Caip19AssetType,
to: Caip19AssetType
): TokenConversionRate;

// {
// rate: '3906.38',
// conversionTime: 1733389786,
// expirationTime: 1733389816,
// }

type OnAssetConversionReturn = {
conversionRate: Record<Caip19AssetType, AssetConversionRate>;
};
```

### Fiat currency representation
Expand Down
Loading