---
# System prepended metadata

title: wallet manager
tags: [v2]

---

---
title: wallet manager
tags: v2
---

# 概述

1. 需要能夠幫客戶建立並管理錢包
2. 錢包分為 transaction wallet 與 asset wallet
    - transaction wallet:
        - 客戶使用 FiO 服務時，FiO 給客戶的錢包
        - 系統自動(背景)作業時，需要錢包簽名
        - 在區塊鏈上，解讀起來像客戶自己發出的紀錄，而非 FiO 代發
        - 在鏈上代表客戶專有，每一筆交易更明確是由客戶發出
    - asset wallet
        - 客戶持有 Wallet
        - 用來儲存資產
        - 客戶或客戶的客戶，沒有錢包概念或不想管理時， FiO 需要提供此服務，方便客戶進行使用
4. 目前使用 vault-ethereum 來產生 wallet，作法是給定一個 account name，即可產生一個 wallet，需要操作此 wallet 的話，就必須使用當初給的 account name 來操作，這個 account name 必須是 unique，不可重複
5. 相關文件
    - https://hackmd.io/LoUkkZ0MRhKTed-3wHjmzA
    - https://trello.com/c/ek2uEkcR/418-fio-wallet-%E8%88%87%E5%B8%B3%E8%99%9F%E7%B6%81%E5%AE%9A%E8%88%87%E5%AE%89%E5%85%A8
    - https://trello.com/c/2EW8njCp/539-fio-vault-ethereum


## 需求

- 記錄錢包與 account 的對應關係

## DB Schema 規劃



```=db
{
    _id: ObjectId,
    nickname: String,
    engine_type: String // EVM...
    account_id: ObjectId,
    type: String, // transaction / asset
    wallet_address: String,
    generated_from: String // vault-ethereum / cybavo,
    created_at: Date
    updated_at: Date
}
```
* engine_type: 屬於哪個引擎，目前是 EVM 未來可能會有 IOTA 或是 SOLANA
* generate_from: 透過哪個 third party 產生的 wallet，vault-ethereum or cybavo...等


~~* index: 相同使用者，相同 type 下的第幾個 wallet，從 0 開始．~~
~~* 假設有一個使用者，已經有兩個交易用的 wallet 了，如果他要再創建一個交易用的 wallet，那麼這時候 index 就會是 2~~
~~> Q: 為什麼要有這個 index~~
~~> A: 因為目前使用 vault-ethereum 來創建 wallet，在創建的時候必須帶入一個 unique 的 account name，由於一個 FiO 的帳號可能會同時有多個 wallet，所以加入此 index 來做區別~~


### vault-ethereum account name 命名規則
```bash
${account_id}_${type}_${wallet_id}
```

> FiO 錢包分成兩種，有兩種使用情境

- transaction： 交易上鏈專用錢包
- asset： 資產錢包

- example:
    - 61ef9113b145007783c4c78b_transaction_6fabc5234babcac2312
    - 61ef9113b145007783c4c78b_asset_6fbabc123b123141


## API 規劃

| HTTP Method | API                          | query string |
| ----------- | ---------------------------- | -------- |
| GET         | /api/v2/wallets              | type     |
| POST        | /api/v2/wallets              |      |
| GET         | /api/v2/wallets/:wallet_id   |      |
| PUT         | /api/v2/wallets/:wallet_id   |      |
| DELETE      | /api/v2/wallets/:wallet_id   |      |

### tms
#### URL: [POST] `/api/v2/wallet/asset`
- call fbms 建立 asset wallet
```yaml=
input: {}

output: {
    wallet_address: String
}

example input: {}

example response:
    Success: {
        code: 0,
        data: {
            wallet_address: 0x5d06f2cC66cDBb11CdF26B6C63be8f4C2B951355
        }
    }
```
#### URL: [LIST] `/api/v2/wallets?type=${type}`
- 查看 user 的錢包
```yaml=
input: {
    type: String, // transaction / asset
}

output: {
    wallet_address: String
}

example input: {
    type: "transaction"
}

example response:
    Success: {
        code: 0,
        data: {
            list: [
                {
                _id: ObjectId('6b5123abcf123321')
                type: "transaction",
                wallet_address: "0x5d06f2cC66cDBb11CdF26B6C63be8f4C2B951355"
                },
                {
                _id: ObjectId('6cf567ab6f6233f1')
                type: "transaction",
                wallet_address: "0x5d06f2cC66cDBb11CdF26B6C63be8f4C2B951355"
                }
            ]            
        }
    }
```

#### URL: [PUT] `/api/v2/wallet/:wallet_id`
- 更改 wallet nickname
```yaml=
input: {
    nickname: String
}

output: {}

example input: {
    nickname: "Micky's little wallet"
}

example response:
    Success: {
        code: 0,
        data: {
            nickname: "Micky's little wallet",
            wallet_address: "0x5d06f2cC66cDBb11CdF26B6C63be8f4C2B951355"
        }
    }
```

#### URL: [DELETE] `/api/v2/wallet/:wallet_id`
- 刪除錢包
```yaml=
input: {}

output: {}

example input: {}

example response:
    Success: {
        code: 0,
        data: {}
    }
```

### fbms
#### URL: [POST] `/api/v2/wallet`
- 建立 wallet
```yaml=
input: {
    wallet_id: ObjectId,
    type: String, // transaction / asset,
    engine_type: String,
    account_id: ObjectId,
}
output: {
    wallet_address: String,
    generated_from: String,
}

example input: {
    wallet_id: ObjectId('6abc123f456afbc65')
    type: "asset",
    engine_type: "EVM",
    account_id: ObjectID('6cb777888bcf12335')
}

example response:
    Success: {
        code: 0,
        data: {
            generated_from: "vault-ethereum",
            wallet_address: 0x5d06f2cC66cDBb11CdF26B6C63be8f4C2B951355
        }
    }
```

#### URL: [DELETE] `/api/v2/wallet/:wallet_id`
- 刪除錢包及其私鑰
```yaml=
input: {
    account_id: ObjectId
    type: String
}

output: {}

example input: {
    type: asset
    account_id: Object('6abc123abcf35344')
}

example response:
    Success: {
        code: 0,
        data: {}
    }

### 規劃文件時 Q&A

> 文凱提問
> 1. 此功能是專為 EVM 架構的錢包設計？ 所以非 EVM 架構錢包，要另外設計？
> 2. 此功能專為 vault-ethereum 設計？ 若未來改用其他 thired party wallet service，這個功能是否會受到影響？ 
> 3. index 是客戶第幾個錢包？ 還是同一組助記詞的 index？
---
> Micky 回答
> 此功能不只想為 EVM 架構的錢包設計，而是為 FiO 上所使用的錢包，不管是不是 EVM 錢包
> 但是當初在設計欄位的時候只考慮到 vault-ethereum，太執著於助記詞的 index 了，考慮之後決定將 index 定義為客戶在相同 type 下的第幾個錢包，如果一個 account_id type 是 asset 已經有兩個錢包，那麼下一個 type 是 asset 的 index 就是 2，index 從 0 開始
> 新增欄位 `engine_type`，來記錄說是哪種 engine，EVM or others
> 新增欄位 `generated_from`，來記錄說是透過哪個 third party 產生的[name=MickyFan]
---
> Joe 提問
> 1. 如果客戶要將資產錢包轉出怎麼辦?
> 答：如果客戶要將資產錢包帶走的話，FiO 就會將錢包的私鑰導出給客戶，並刪除關於此錢包的所有相關資訊 [name=MickyFan]
> 2. index 是否會讓人混淆，誤以為是 BIP-32 的索引 [參考](https://ithelp.ithome.com.tw/m/articles/10279944)
> 答: 原本設計 index 最主要是為了給 vault-ethereum 做區分用的，看起來很容易造成誤解，決定拿掉 index，改用 wallet_id 做區分 [name=Micky]
> 3. generated_from 這個名稱不夠直白
> 答: 將 generated_from 改成 generated_from [name=Micky]
> 4. transaction 如果不是平時有在做交易的人，可能無法快速理解
> 答: 將 transaction 都寫成全名 transaction [name=Micky]
> 5. 需不需要有 delete wallet 的 API? 也可以做成軟刪除
> 答: 考慮過後覺得可能會有用到的時候，但是不做成軟刪除，確認刪掉之後就會永久消失在 FiO 上(下面有參考 thirdweb 做的刪除前警告)
> ![](https://i.imgur.com/o67REo0.png) [name=Micky]

https://thirdweb.com/dashboard
