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 import { normalTxActionBuilder, issueAssetTxActionBuilder } from './transactions'
8 const type = 'transaction'
10 const list = baseListActions(type, {
13 const form = baseCreateActions(type)
15 function preprocessTransaction(formParams) {
16 const copy = JSON.parse(JSON.stringify(formParams))
18 baseTransaction: copy.baseTransaction,
19 actions: copy.actions || [],
22 if (formParams.form === 'normalTx') {
23 const gasPrice = formParams.state.estimateGas * Number(formParams.gasLevel)
24 builder.actions = normalTxActionBuilder(formParams, Number(gasPrice), 'amount')
27 if (formParams.form === 'issueAssetTx') {
28 builder.actions = issueAssetTxActionBuilder(formParams, 'amount')
32 if (builder.baseTransaction == '') {
33 delete builder.baseTransaction
36 if (formParams.submitAction == 'generate') {
37 builder.ttl = '1h' // 1 hour
40 for (let i in builder.actions) {
41 let a = builder.actions[i]
43 const intFields = ['amount', 'position']
44 intFields.forEach(key => {
47 if ((parseInt(value) + '') == value) {
48 a[key] = parseInt(value)
50 throw new Error(`Action ${parseInt(i) + 1} ${key} must be an integer.`)
56 a.referenceData = parseNonblankJSON(a.referenceData)
58 throw new Error(`Action ${parseInt(i) + 1} reference data should be valid JSON, or blank.`)
62 a.receiver = parseNonblankJSON(a.receiver)
64 throw new Error(`Action ${parseInt(i) + 1} receiver should be valid JSON.`)
71 form.submitForm = (formParams) => function (dispatch) {
72 const client = chainClient()
74 const builderFunction = ( builder ) => {
75 const processed = preprocessTransaction(formParams)
77 builder.actions = processed.actions
78 if (processed.baseTransaction) {
79 builder.baseTransaction = processed.baseTransaction
83 const submitSucceeded = () => {
84 dispatch(form.created())
86 pathname: '/transactions',
93 // normal transactions
94 if( formParams.form === 'normalTx'){
96 const accountId = formParams.accountId
97 const accountAlias = formParams.accountAlias
98 const accountInfo = Object.assign({}, accountAlias!== ''? {alias: accountAlias}: {id: accountId})
100 return client.accounts.query(accountInfo)
102 if(resp.data[0].xpubs.length > 1){
103 throw {code: 'F_BTM003'}
105 const body = Object.assign({}, {xpub: resp.data[0].xpubs[0], password: formParams.password})
106 return client.mockHsm.keys.checkPassword(body)
109 if(!result.data.checkResult){
110 throw new Error('PasswordWrong')
112 return client.transactions.build(builderFunction)
115 const body = Object.assign({}, {password: formParams.password, transaction: tpl.data})
116 return client.transactions.sign(body)
119 if(!signed.data.signComplete){
120 throw {code: 'F_BTM100'}
122 return client.transactions.submit(signed.data.transaction.rawTransaction)
124 .then(submitSucceeded)
127 //advanced transactions
128 else if( formParams.form === 'advancedTx' ){
129 const buildPromise = (formParams.state.showAdvanced && formParams.signTransaction) ? null :
130 client.transactions.build(builderFunction)
132 if (formParams.submitAction == 'submit') {
133 const signAndSubmitTransaction = (transaction) => {
134 const body = Object.assign({}, {password: formParams.password, transaction: transaction})
135 return client.transactions.sign(body)
136 .then( signed => client.transactions.submit(signed.data.transaction.rawTransaction) )
137 .then(submitSucceeded)
140 if( formParams.state.showAdvanced
141 && formParams.signTransaction ){
142 const transaction = JSON.parse(formParams.signTransaction)
143 return signAndSubmitTransaction(transaction)
147 .then(tpl => signAndSubmitTransaction(tpl.data))
150 // submitAction == 'generate'
151 const signAndSubmitGeneratedTransaction = (transaction) => {
152 const body = Object.assign({}, {password: formParams.password, transaction: transaction})
153 return client.transactions.sign(body)
157 type: 'GENERATED_TX_HEX',
160 hex: JSON.stringify(resp.data.transaction),
163 dispatch(push(`/transactions/generated/${id}`))
167 if (formParams.state.showAdvanced
168 && formParams.signTransaction) {
169 const transaction = JSON.parse(formParams.signTransaction)
170 return signAndSubmitGeneratedTransaction(transaction)
174 .then(resp => signAndSubmitGeneratedTransaction(resp.data))
177 //issue Asset transactions
178 else if( formParams.form === 'issueAssetTx'){
180 const signAndSubmitTransaction = (transaction) => {
181 const body = Object.assign({}, {password: formParams.password, transaction: transaction})
182 return client.transactions.sign(body)
184 if(!signed.data.signComplete){
187 type: 'GENERATED_TX_HEX',
190 hex: JSON.stringify(signed.data.transaction),
193 dispatch(push(`/transactions/generated/${id}`))
196 return client.transactions.submit(signed.data.transaction.rawTransaction)
197 .then(submitSucceeded)
202 if (formParams.submitAction == 'submit') {
203 return client.transactions.build(builderFunction)
204 .then(tpl => signAndSubmitTransaction(tpl.data))
207 if( formParams.submitAction == 'sign' ){
208 const transaction = JSON.parse(formParams.signTransaction)
209 return signAndSubmitTransaction(transaction)
215 const decode = (data) => {
216 return (dispatch) => {
217 return chainClient().transactions.decodeTransaction(data)
219 if (resp.status === 'fail') {
220 dispatch({type: 'ERROR', payload: {'message': resp.msg}})
222 dispatch({type: 'DECODE_TRANSACTION', data:resp.data})