---
# System prepended metadata

title: 票券上鏈系統
tags: [SPEC, BITCOIN]

---

# 票券上鏈系統

`2020.01.16 refactor` 
`2019.11.20 api-v3`
`2019.10.07 modified`
`2019.10.04 modified`
`2019.09.03 modified`
`2019.07.23 created`

---

[TOC]

---

## <span style="color:red">API</span>

### Public

#### Get Server Timestamp `GET /api/now`
Response:
```javascript
{
  "timestamp": 1570248114563, // A Number representing the milliseconds elapsed since the UNIX epoch.
  "ISOString": // A string representing the given date in the ISO 8601 format according to universal time.
}
```

### Authorized

---

* header: `X-TICKET-TOKEN: <token>`
* header: `X-TICKET-HMAC: <HMAC>`
* HMAC Example:
  ```javascript
  // Node.js
  const hmac = require('crypto')
    .createHmac('sha512', keyStr)
    .update(payloadStr)
    .digest('hex')
  ```
  ```javascript
  // Javascript
  const hmac = require("crypto-js")
    .HmacSHA512(payloadStr, keyStr)
    .toString(require("crypto-js").enc.Hex)
  ```
  ```php
  // Php
  $hmac = hash_hmac('sha512', $payload_str, $key_str);
  ```
  Say, ... https://www.freeformatter.com/hmac-generator.html#ad-output ![](https://i.imgur.com/xK8ZJk8.png)
  `185beceee65a5ed7e43f7cc98530bfab1b0d00679488a47225255d04594fd7f17ed6908e7a08df57ac14c9e56c2fdef83ee9adaf9df2ff9f61465898c5d78c00`
---
#### App Url Format

* https://ipfs.io/ipfs/QmQDDrBT2mCPUW8A6a43xeAkP6GKqHTRQ3dFUK2YQ1oLuz/?sn=0000000000

---
#### Create A new Vendor `POST /api/{user}/vendors`
Request
```javascript
{
  "name": "My Non-Fungible Tickets",
  "symbol": "MNFT"
}
```
Response
```javascript
{
  "name": "My Non-Fungible Tickets",
  "symbol": "MNFT",
  "transaction": "...",
  "contract": "..."
}
```

#### Get A Vendor
Path: `Get /api/{user}/vendors/{contract}`

#### Get All Vendors
Path: `Get /api/{user}/vendors`

#### Create A New Ticket
Path: `POST /api/{user}/tickets/{contract}`
Request
```javascript
{
  "info": {
    "id": '34', // **商品編號** (string represets a decimal number)
    "name": "田馥甄 2020 演唱會",
    ~~"cap": "2000",~~ // **Removed**
    "url": "https://...",
    "inception": "2019-11-19T10:58:29+08:00",
    "expiration": "2019-11-19T10:58:29+08:00"
  }
}
```
Response
```javascript
{
  "info": { ... },
  "transaction": "...",
  "state": { ... },
  "ticketId": 4321
}
```

#### **Update A Ticket**
Path: `PATCH /api/{user}/tickets/{contract}/{ticketId}`
Request
```javascript
{
  "data": [
    {
      "sn": "0000000000",
      "owner": "...",
      "sold": "2019-11-19T10:58:29+08:00",
      "redeemed": "...",
      "invalid": "..."
    },
    {
      "sn": "0000000001",
      "owner": "...",
      "sold": "2019-11-19T10:58:29+08:00",
      "redeemed": "...",
      "invalid": "..."
    },
    ...
  ]
}
```
Response
```javascript
{
  account: 'dev',
  contract: '0xd6aE7257CC4C24eC5272D1138A7eF5f9B30eDb8D',
  info:
   { pn: 'fe40298c',
     name: '田馥甄 97fb 演唱會',
     cap: '25',
     uri: 'https://350f6a2cba1e242e2018b5996b629143',
     inception: '2020-01-19T10:58:29+08:00',
     expiration: '2020-01-19T10:58:29+08:00' },
  meta:
   { name: '田馥甄 97fb 演唱會',
     contract:
      'https://ropsten.etherscan.io/token/0xd6a...',
     updated_at: '2020-01-14T16:16:02+08:00' },
  state:
   { ipfs:
      'https://ipfs.io/ipfs/QmRK8or6msts5xoJZ5Gx3J8yx5RYv6Z3ZB4yAXbn5NtPes',
     updatedAt: '2020-01-16T11:48:56+08:00' },
  ticket_id: 0,
  transaction:
   '0x6dbdad55da2fec4d035edc407901c9553b4db068e4c442302e1b265a7799e57f',
  last_transaction:
   '0xfadf616deaf8f7863e5966791ca80304051d3a07e8e614927efb91696529d8b0' }
}
```


~~#### Get A Ticket~~
Path: `GET /api/{user}/tickets/{contract}/{ticketId}`

#### Get All Contract Tickets
Path: `GET /api/{user}/tickets/{contract}`

#### Get All Tickets
Path: `GET /api/{user}/tickets`

#### Get A Transaction
Path: `GET /api/{user}/transactions/{transaction}`

#### Get All Transactions
Path: `GET /api/{user}/transactions`

#### Get Wallets Info
Path: `GET /api/{user}/wallets`

## 系統預定規格概述

```mermaid
graph TD
    api-user --- server
    resp-api --- full-node
    subgraph Ethereum Blockchain
    contracts --- full-node
    end
    subgraph Cloud Server
    resp-api --- server
    end

    style full-node fill,stroke:#f6,stroke-width:px,stroke-dasharray: 5, 5
    style api-user fill,stroke:#f6,stroke-width:px,stroke-dasharray: 5, 5
```
本專案之系統包含了

1. 乙太坊上智能合約軟體；
2. 與 1 互動溝通的伺服器軟體 (REST API)；
3. 運行 2 的伺服器架設代管；
4. 系統文件。

軟體包合兩部份，其一為使用乙太坊區塊鏈技術的上智能合約；其二為用來與區塊鏈互動的一 REST API，分別描述如下：

1. 乙太坊上一個或多個智能合約軟體 (*Smart Contract*)：功能包含
   * Ownership:
     * 特定權限的乙太帳戶才能執行指定操作；
     * 合約所有權轉移功能。
   * Operation:
     * 產生新票種、鏈上記錄該票種必要資訊。
     * 產生新票卷、鏈上記錄該票卷必要資訊、鏈上更新票該卷狀態。
   * 該合約應在測試階段部署在乙太坊公開測試鏈 (Ropsten Testnet)；在運營階段部署在乙太坊公開主鏈 (Mainnet)
       * Mainnet Browser: https://etherscan.io/
       * Ropsten Brower: https://ropsten.etherscan.io/
2. 與智能合約互動的 REST API (a backend software)：功能包含
    * 能夠對接上述智能合約，讀取合約、寫入合約、追蹤交易。
    * 管理管理者的乙太帳戶、私鑰、乙太幣。
    * REST API Routes
      * 建立一新票種 (create/post)
      * 查詢特定票種 (get/get)
      * 更新特定票種狀態 (update/patch)
        * 發特定票卷 (mint token)
        * 更新特定票卷狀態 (set sold/redeeemed/invalid state)
      * 查詢 transaction 結果/確認數 (get)
    * REST API Authentication
      * Token: 識別 API USER 身份
      * Secret: 驗證 API USER 身份
      * Timestamp: 防止重送攻擊
3. 伺服器架設、代管部份：
    * 除 REST API 伺服器外另需一乙太坊的區塊鏈全節點 (Full Node) 將選用穩定可靠的第三方乙太全節點服務 (如 https://infura.io/ )。伺服器運行費用另計。
4. 文件。除軟體服務外，本系統應包含說明文件，並區分為
    * 技術文件 (Technical Specification)：技術人員使用，包含完整規格、系統原理、運作方式，以供未來技轉或專案重啟使用。
    * 操作文件 (Operational Specification)：非技術人員使用，包含基本操作、系統概觀、維運成本概算、金流/私錀管理等注意事項。


### <span style="color:red">ITEMS</span>

* 票種 (TICKET) 上鏈資訊? (活動卷、商品卷)
  - [ ] name (票種名稱 e.g. "United State Dollar")
  - [ ] symbol (票種縮寫 e.g. "USD")
  - [ ] info:
      - [ ] id (票種編號)
      - [ ] cap (發行張數)
      - [ ] url (web/ipfs 網址-可放 logo 圖等)
      - [ ] class ({ 活動卷、商品卷 ... })
      - [ ] start (開始日期)
      - [ ] expiration (結束日期)
* 票券 (TOKEN) 上鏈資訊?
  - [ ] token id (流水號, 0, 1, 2, 3, ...)
  - [ ] owner:
      - [ ] 方案一: uid 明碼 (e.g. `5dc147-b4b444-1b3fbf-43f450`)
      - [ ] 方案二: uid+hash (e.g. `c89ba2b2caf8b....`)
      - [ ] 方案三: eth addr (e.g. `0x5774ae4bD....`) (ps. the private key will be generated by HD Wallet architecture, with node path = uid) (In brief, a `seed` + `uid` -> `private-key` -> `public-key`=address)
  - [ ] states: timestamp
    - [ ] 1. sold  (已上鏈) `2019-11-06T07:52:35.341Z GMT+0`
    - [ ] 2. redeemed (已使用) `2019-11-06T07:52:35.341Z GMT+0`
    - [ ] 3. invalid (已作廢) `   `
    * <span style="color:blue">stateA (信託狀態)</span>: 未使用、已使用、已作廢、請款中、已請款
    * <span style="color:blue">stateB (票卷狀態)</span>: (已上鏈)、未使用、已使用、已作廢、已過期
    * <span style="color:blue">stateC (平台請款狀能)</span>: 無、(可請款)、已作廢、請款中、請款完成、請款失敗
* 鏈上操作數量級 (頻率/個數)
  - [ ] `POST /tickets` (name, symbol, info)
  - [ ] `PATCH /tickets/:contract/batchMint` (<span s style="color:red">tokenIds, toAddresses,</span> sold)
  - [ ] `PATCH /tickets/:contract/setStateRedeemed` (tokenId, timestring)
  - [ ] `PATCH /tickets/:contract/setStateInvalid` (tokenId, timestring)
* 消耗費用
  * GCP 費用: $25~$50/M
  * INFURA 費用:
      * $0/M: 100K Request / Day
      * $50/M: 200K Request / Day
  * TRX 費用: https://ethgasstation.info/calculatorTxV.php
      * gas: mint 100 張: 4929764
* Blocks
  ```mermaid
  graph LR
    
    Contract-Matrix -->|created| Contract-TicketA
    
    Admin -->|owner| Contract-Matrix
    
    Admin -->|owner| Contract-TicketA
    
    
    Api-Server -.->|priv| Admin
    
    Api-Server -.->|priv| Admin
    
    Minter -.- Contract-TicketA
    
    Minter -->|mint| user1
    Minter -->|mint| user2
    Minter -->|mint| user3
    
    Operator -->|transfer|user1
    Operator -->|transfer|user2
    Operator -->|transfer|user3
 
    style Contract-Matrix fill:#f9f,stroke:#333,stroke-width:4px,coler:#333,font-size:5px
    style Contract-TicketA fill:#f9f,stroke:#333,stroke-width:4px
  ```
### Ref

* https://drive.google.com/file/d/0B-T4BwVnxLmOdmlXTTREcUNCcHE0RzdRR1lMaF92THFUS1U0/view?usp=sharing
* ![](https://i.imgur.com/w3Ilrlg.png)





## Reference

### 2020-01-16

- [ ] Ticket sn
- [ ] Vendor Identification (`SYMBOL`)
- [ ] Uncapped Ticket
- [ ] ipfs front end
- [ ] DeERC721

### DEMO

* account
* network
```bash=
npx truffle compile
# NAME, SYMBOL, MORE_OPERATOR
npx truffle migrate -f 2 --to 2 --network ropsten
# MATRIX_ADDR

npx truffle-flattener ./contracts/Matrix.sol > ./flat.sol
sed -i 's/pragma experimental ABIEncoderV2;//g' flat.sol
{ echo 'pragma experimental ABIEncoderV2;'; cat flat.sol; } | tee flat.sol > /dev/null

scp x240-gcpdev:~/ticket/contract/flat.sol .
mv ./flat.sol $USERPROFILE/Desktop
# verification

npx truffle exec ./scripts/tests/mintANewToken.js --network ropsten
npx truffle exec ./scripts/tests/updateATokenState.js --network ropsten
```

###### tags: `SPEC` `BITCOIN`