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

CHIP-0002: Add dApp protocol #9

Merged
merged 33 commits into from
Oct 25, 2022
Merged
Changes from 8 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
55a14ce
Add dApp protocol proposal
Apr 20, 2022
21db5ff
update some methods, add rationale & reference implementation setctions
Apr 25, 2022
01b4ffc
update methods and remove createAssetTx
Apr 27, 2022
d0ea2b9
add getPublicKeyByAddress method & additional description
Apr 28, 2022
b4dad7c
change to CHIP0002 & Draft status
Apr 28, 2022
c8b9e60
remove IETF RFC Spec & update Comments-URI
Apr 29, 2022
8543505
Merge branch 'Chia-Network:main' into chip0002
Apr 29, 2022
d3026ea
update methods
Apr 29, 2022
fc9140d
format & add types
May 10, 2022
2868c7d
change to browser.tabs.sendMessage & fix typo
May 12, 2022
53f5763
format
May 13, 2022
5f7a07d
remove Transfer, CreateOffer & TakeOffer
May 15, 2022
ea6d43f
add a `puzzle` return parameter & remove duplicated CoinSpend
May 25, 2022
36b488f
format
May 25, 2022
39fec69
unify function naming
Jun 5, 2022
c18a8dd
update rationale
Jun 5, 2022
67731b5
add more desc & update security section
Jun 7, 2022
47b542b
add example.js
Jun 8, 2022
aaa1c61
support NFT & DID
Jun 16, 2022
7d8ff8d
format
Jun 16, 2022
20c9980
simplify the APIs & add pagination
Jun 25, 2022
1953e38
update `getPublicKeys` desc
Jun 28, 2022
71820aa
fix typos
Jul 10, 2022
fc8be6a
detect wallet name
Jul 12, 2022
eef816d
add apiVersion & wallet version
Jul 17, 2022
c9f162f
add newly-defined functions in example.js
Aug 10, 2022
c75136c
change to Review status
Aug 17, 2022
1a67cbf
change pagination of getAssetCoins
Aug 26, 2022
061de4c
suppor partialSign
Sep 5, 2022
5fae81d
update to Last Call
Sep 13, 2022
73061c3
change signMessage method & revert to Review status
Oct 1, 2022
35e9f82
update to Last Call
Oct 11, 2022
7434568
Change status of 0002
Oct 25, 2022
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
386 changes: 386 additions & 0 deletions CHIPs/chip-0002.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,386 @@
CHIP Number | 0002
:-------------|:----
Title | dApp protocol
Description | This proposal describes a Web3 bridge between the browser wallets and dApps on the Chia Network.
Author | [Dimitry Suen](https://github.com/dimitrysuen)
Comments-URI | https://github.com/Chia-Network/chips/pull/9
Status | Draft
Category | Process
Sub-Category | Procedural
Created | 2022-04-19
Requires | None
Replaces | None
Superseded-By | None

## Abstract

This proposal describes a Web3 bridge between the browser wallets and dApps on the Chia Network.

## Motivation

More and more decentralized apps are emerging on the Chia Network. As an important entrance to Web3, a user-friendly plug-in browser wallet makes it easier for users to interact on the Chia Network. Meanwhile, dApps require access to call the user's wallet, typically from a web context.

We propose this dApp protocol for discussion with developers to improve. We hope that Chia Network's browser plug-in wallets will follow this standard to simplify the integration development of dApps.
We also point out some problems that we are considering in this draft. Feel free to comment.

## Backwards Compatibility

The parameters are currently passed via `JSON,` which can be modified for subsequent expansion.

## Rationale

We did a lot of research on the different dApp protocols. Especially, Cardano is also based on the UTXO model, but this proposal is quite different from CIP-30. In addition to `signTx`, we also encapsulate some specific methods, such as offer-related. What's more, the smart contract models of Cardano and Chia are pretty different. Considering that many custom puzzles appear on the Chia network, we propose a more robust design balancing flexibility and security.

## Goal

We manage our users' coins and private keys while maintaining the security and privacy of their funds. Our primary principle is to protect the assets' security and privacy and maintain compatibility with Chia Wallet as much as possible.

## Requirements

None.

## Specification

All methods can be called via `window.chia`, such as

```tsx
interface RequestArguments {
method: string;
params?: object;
}
window.chia.request(args: RequestArguments): Promise<any>;
mariano54 marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

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

We should make it clear that any request might take a while (Several minutes) because the user has to approve manually. Is this true?

```

The dApps and wallet use `chrome.tabs.sendMessage` to communicate, the `request` function is a wrapper for the `sendMessage` function.
This proposal aims to specify an underlying API that third-party libraries can wrap like "wallet.reqestAddresses()" so that they can provide additional features, such as type hint.

## Methods

### addresses
Return a list of `standard puzzleHash`. The number of addresses returned depends on the wallet implementation. If dApp is not approved, API will return an empty list.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we define standard puzzle hash? If the wallet wants to use a different type of puzzle than another wallet, that's fine right?

Copy link
Contributor

Choose a reason for hiding this comment

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

We should just say: XCH address. XCH will be sent directly to this address, so this should not be a wrapper CAT address, for example

The dApp can build special CAT puzzleHash from the `standard puzzleHash`.

```tsx
addresses(): string[]
```

### chainId

Return the current chainID.

| CHAIN NAME | CHAINID |
|------------|-----------|
Copy link
Contributor

Choose a reason for hiding this comment

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

we might want to specify "Chia Mainnet" on the left

| Mainnet | mainnet |
| Testnet10 | testnet10 |

```tsx
chainId(): string
```

### connect()

mariano54 marked this conversation as resolved.
Show resolved Hide resolved
The dApp requests users' permission to connect the wallet. If the user rejects the request, the API will throw `userRejectdRequestError`.
Copy link
Contributor

Choose a reason for hiding this comment

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

What does connect imply? Does this give read access to all the users data? It definitely does not give write access, correct?


```tsx
connect(): void
```

### walletSwitchChain

dApps request to switch to another chain

```tsx
walletSwitchChain(params: {chainId: string}): void
```

### transfer
mariano54 marked this conversation as resolved.
Show resolved Hide resolved
dApps transfer asset. The wallet will handle the tx fee and broadcast the tx.

Parameters as described below.
| Parameter | Description |
|-----------|----------------------------------------------------------------------------------|
| to | bech32-encoded address with network prefix |
| amount | the transfer amount, unit is `mojo` |
| assetId | the asset id in the CAT1 standard. It is `null` when transferring native tokens. |
| memos | this is optional. The value is hex string array |

```tsx
interface TransferParams {
to: string;
amount: number;
assetId: string|null;
memos?: string[];
}

interface TransferResp {
transaction_id: string;
transaction: SpendBundle;
}

transfer(params: TransferParams): TransferResp
```

### takeOffer
dApps take `offer.` The wallet will handle the tx fee. The wallet will broadcast the tx.

Parameters as described below.
| Parameter | Description |
|-----------|-------------------------------|
| offer | bech32-encoded `offer` string |

```tsx
interface TakeOfferResp {
transaction_id: string;
transaction: SpendBundle;
}

takeOffer(params: {offer: string}): TakeOfferResp
```

### createOffer
dApps create `offer,` which returns the bech32-encoded `offer` string.

| Parameter | Description |
|---------------|------------------------------------------------------------------|
| offer | the assets the user will pay |
| requestAssets | the assets the user wants |
| fee | this is optional. If it is none, the wallet will handle the fee. |

```tsx
interface AssetAmount {
assetId: string|null;
amount: string|number;
}

interface createOfferParams {
offerAssets: AssetAmount[];
requestAssets: AssetAmount[];
fee?: string|number;
}

interface createOfferResp {
transaction_id: string;
offer: string;
}

createOffer(params: createOfferParams): createOfferResp
```

### selectAssetCoins
API returns the spendable coins for the selected CAT.

Parameters as described below.
| Parameter | Description |
|-----------|---------------------------------------------------------------------------------------------------------------------------------------------|
| assetId | The CAT1 asset id. It will be `null` if the user selects native tokens |
| amount | This is optional. All the coins(included locked coin) will be returned if it is missing. Otherwise, API will return the unlocked coins only. |
| excludes | This is optional. This value is the `name` of coins. |

```tsx
interface SelectAssetCoinsParams {
assetId: string|null;
amount?: number|string;
excludes?: string[];
}

interface Coin {
parent_coin_info: string;
puzzle_hash: string;
amount: number;
}

interface CoinRecord {
coin: Coin;
coinName: string;
confirmedBlockIndex: number;
timestamp: number;
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need the timestamp?

locked: boolean;
}

selectAssetCoins(params: SelectAssetCoinsParams): CoinRecord[]
```

### getAssetBalance
Copy link
Contributor

Choose a reason for hiding this comment

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

This is just a convenience method, because we can call selectAssetCoins and add up the amount right?

return the spendable balance of the wallet. It's convenient for the dApp to query the user's balance.

Parameters as described below.
| Parameter | Description |
|-----------|--------------------------------------------------------------------|
| assetId | The CAT1 asset id. It will be `null` if the user selects native tokens |

```tsx

interface AssetBalanceResp {
confirmed: string;
spendable: string;
spendableCoinCount: number;
}

getAssetBalance(params: {assetId: string|null}): AssetBalanceResp

```

### getPublicKeyByAddress
return the public key asscociated with the address.

Parameters as described below.
| Parameter | Description |
|-----------|-----------------------------------|
| address | the data from method `addresses` |

```tsx
getPublicKeyByAddress(params: {address: string}): string
```

### signTx

This is a lower-level API that signs custom coin spends. API return a signed `SpendBundle`. Besides users' coins, it also supports the coins not owned by the user. For security purposes, the wallet should check if `coin.puzzle_hash` and `hash(puzzle_reveal)` are equal and the `conditions` generated by the coin satisfy the specification. The wallet will track the signed transactions. The coins in the transaction will be locked and not be returned in `selectAssetCoins`.

Please note that, for security purposes, the `AGG_SIGN_UNSAFE` in the `conditions` will be ignored.

Parameters as described below.
| Parameter | Description |
|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| coinSpends | a list of `coinSpend` |
| coinSpend.coin | The value can be `Coin` or `coinName`. For user's coin, this value should be `coinName`. |
| coinSpend.puzzle_reveal | if the `coinSpend.coin` is the `coinName`, this field will be ignore, wallet will fill it with correct coin puzzle |
| coinSpend.solution | the solution of puzzle |
| broadcast | this is optional. It means whether the wallet broadcasts the tx to the full node. If the value is `True`, an Error will be thrown if the tx is invalid |

```tsx
interface CoinSpend {
coin: Coin|string;
puzzle_reveal: string;
solution: string;
}

interface SignTxParams {
coinSpends: CoinSpend[]
broadcast?: boolean
}

interface SignTxResp {
transaction_id: string;
transaction: SpendBundle;
}

signTx(params: SignTxParams): SignTxResp
```

### signMessage
Sign the message encoded as a hex string using the private key associated with the address's private key.
The internal implementation in the wallet is `bls_sign(private_key, sha256("\x18Chia Signed Message:\n" + len(message) + message))`. To prevent replay attacks, dApps should add the current `networkId` and `timestamp` into the message. If the dApp doesn't care which chain they're on, they can include the `timestamp` only.

Choose a reason for hiding this comment

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

For len(message) values that don't fit in a single byte, is there an expected byte ordering here? Network byte order would be what I would expect.


Parameters as described below.
| Parameter | Description |
|-----------|-----------------------------------|
| message | the hex string needs to be signed |
| address | the data from method `addresses` |

```tsx
interface SignMessageParams {
message: string;
address: string;
}

interface SignMessageResp {
publicKey: string;
signature: string;
}

signMessage(params: SignMessageParams): SignMessageResp
```

### pushTx

Even if the wallet supports `pushTx,` we still highly recommend that the dApp uses its full node to broadcast transactions.

```tsx
interface PushTxParams {
spendBundle: SpendBundle;
}

interface PushTxResp {
// mempool status, success/pending/failed
status: string;
dimitrysuen marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe add a list of statuses, because it's possible the wallet might be connected to multiple nodes in the future.

}

pushTx(params: PushTxParams): PushTxResp
```

## Events

### chainChanged

the bridge emits `chainChanged` when connecting to a new chain

```tsx
chia.on('chainChanged', listener: (chainId: string) => void)
```

### addressesChanged

the bridge emits `addressesChanged` if the addresses change account in the wallet
Copy link
Contributor

Choose a reason for hiding this comment

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

What does this mean? Does it mean a new address was created? or the active key was changed?


```tsx
chia.on('addressesChanged', listener: (addresses: string[]) => void)
```

mariano54 marked this conversation as resolved.
Show resolved Hide resolved
## Errors

```tsx
interface Error {
code: number;
message: string;
data?: any;
}
```

```tsx
invalidParamsError = {
code: 4000,
message: 'invalidParams'
}

unauthorizedError = {
code: 4001,
message: "unauthorized"
}

userRejectdRequestError = {
code: 4002,
message: "userRejectdRequest"
}

spendableBalanceExceeded = {
code: 4003,
message: 'spendableBalanceExceeded',
}

limitExceed = {
code: 4029,
message: 'too many requests'
}
```

## Test Cases

## Security

## Additional Assets

None.

## Reference Implementation

The [Goby](https://goby.app) team has implemented the methods described above.

1. https://github.com/Chia-Network/chia-blockchain/blob/main/chia/rpc/wallet_rpc_api.py
2. https://github.com/ChainSafe/web3.js
3. https://github.com/cardano-foundation/CIPs/tree/master/CIP-0030
4. https://vacuumlabs.github.io/ledgerjs-cardano-shelley/5.0.0/index.html
5. https://github.com/solana-labs/wallet-adapter

## Copyright

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).