OSDN Git Service

add advanced build transaction options
[bytom/bytom-electron.git] / src / features / transactions / actions.js
1 import uuid from 'uuid'
2 import { chainClient } from 'utility/environment'
3 import { parseNonblankJSON } from 'utility/string'
4 import { push } from 'react-router-redux'
5 import { baseCreateActions, baseListActions } from 'features/shared/actions'
6
7 const type = 'transaction'
8
9 const list = baseListActions(type, {
10   defaultKey: 'id'
11 })
12 const form = baseCreateActions(type)
13
14 function preprocessTransaction(formParams) {
15   const copy = JSON.parse(JSON.stringify(formParams))
16   const builder = {
17     baseTransaction: copy.baseTransaction,
18     actions: copy.actions,
19   }
20
21   if (builder.baseTransaction == '') {
22     delete builder.baseTransaction
23   }
24
25   if (formParams.submitAction == 'generate') {
26     builder.ttl = '1h' // 1 hour
27   }
28
29   for (let i in builder.actions) {
30     let a = builder.actions[i]
31
32     const intFields = ['amount', 'position']
33     intFields.forEach(key => {
34       const value = a[key]
35       if (value) {
36         if ((parseInt(value)+'') == value) {
37           a[key] = parseInt(value)
38         } else {
39           throw new Error(`Action ${parseInt(i)+1} ${key} must be an integer.`)
40         }
41       }
42     })
43
44     try {
45       a.referenceData = parseNonblankJSON(a.referenceData)
46     } catch (err) {
47       throw new Error(`Action ${parseInt(i)+1} reference data should be valid JSON, or blank.`)
48     }
49
50     try {
51       a.receiver = parseNonblankJSON(a.receiver)
52     } catch (err) {
53       throw new Error(`Action ${parseInt(i)+1} receiver should be valid JSON.`)
54     }
55   }
56
57   return builder
58 }
59
60 form.submitForm = (formParams) => function(dispatch) {
61   const buildPromise = chainClient().transactions.build(builder => {
62     const processed = preprocessTransaction(formParams)
63
64     builder.actions = processed.actions.map(action => {
65       let result = {
66         address: action.address,
67         amount: action.amount,
68         account_id: action.accountId,
69         account_alias: action.accountAlias,
70         asset_id: action.assetId,
71         asset_alias: action.assetAlias,
72         type: action.type,
73       }
74       if (action.receiver) {
75         result.receiver = {
76           control_program: action.receiver.controlProgram,
77           expires_at: action.receiver.expiresAt
78         }
79       }
80       return result
81     })
82     if (processed.baseTransaction) {
83       builder.baseTransaction = processed.baseTransaction
84     }
85   })
86
87   if (formParams.submitAction == 'submit') {
88     return buildPromise
89       .then((resp) => {
90         if (resp.status === 'fail') {
91           throw new Error(resp.msg)
92         }
93
94         const tpl = resp.data
95         const password = (tpl.signing_instructions || []).map(() => '123456')
96         const client = chainClient()
97         const body = Object.assign({}, {password, 'transaction': tpl})
98         return client.connection.request('/sign-submit-transaction', body, true)
99       }).then(resp => {
100         if (resp.status === 'fail') {
101           throw new Error(resp.msg)
102         }
103
104         dispatch(form.created())
105         dispatch(push({
106           pathname: '/transactions'
107         }))
108       })
109   }
110
111   // submitAction == 'generate'
112   return buildPromise.then(resp => {
113     if (resp.status === 'fail') {
114       throw new Error(resp.msg)
115     }
116
117     const tpl = resp.data
118     const password = (tpl.signing_instructions || []).map(() => '123456')
119     const client = chainClient()
120     const body = Object.assign({}, {password, 'transaction': tpl})
121     return client.connection.request('/sign-transaction', body, true)
122   }).then(resp => {
123     if (resp.status === 'fail') {
124       throw new Error(resp.msg)
125     }
126     const id = uuid.v4()
127     dispatch({
128       type: 'GENERATED_TX_HEX',
129       generated: {
130         id: id,
131         hex: resp.data.raw_transaction,
132       },
133     })
134     dispatch(push(`/transactions/generated/${id}`))
135   })
136 }
137
138 export default {
139   ...list,
140   ...form,
141 }