@@ -10,9 +10,10 @@ import {
10
10
IKeyringPair ,
11
11
ISubmittableResult ,
12
12
} from '@polkadot/types/types'
13
- import { BN , stringCamelCase } from '@polkadot/util'
13
+ import { BN , bnToBn , stringCamelCase } from '@polkadot/util'
14
14
import { decodeOutput } from './decodeOutput'
15
15
import { getAbiMessage } from './getAbiMessage'
16
+ import { getBalance } from './getBalance'
16
17
import { getMaxGasLimit } from './getGasLimit'
17
18
18
19
/**
@@ -68,8 +69,17 @@ export const contractQuery = async (
68
69
export type ContractTxResult = {
69
70
dryResult : ContractCallOutcome
70
71
result ?: ISubmittableResult
71
- errorMessage ?: string | 'UserCancelled' | 'ExtrinsicFailed' | 'Error'
72
+ errorMessage ?:
73
+ | string
74
+ | 'UserCancelled'
75
+ | 'ExtrinsicFailed'
76
+ | 'TokenBelowMinimum'
77
+ | 'Error'
72
78
errorEvent ?: EventRecord
79
+ successEvent ?: EventRecord
80
+ extrinsicHash ?: string
81
+ extrinsicIndex ?: number
82
+ blockHash ?: string
73
83
}
74
84
export const contractTx = async (
75
85
api : ApiPromise ,
@@ -80,6 +90,18 @@ export const contractTx = async (
80
90
args = [ ] as unknown [ ] ,
81
91
statusCb ?: Callback < ISubmittableResult > ,
82
92
) : Promise < ContractTxResult > => {
93
+ // Check if account has sufficient balance
94
+ const accountAddress = typeof account === 'string' ? account : account . address
95
+ const { freeBalance } = await getBalance ( api , accountAddress )
96
+ const hasZeroBalance = ! freeBalance || freeBalance . isZero ( )
97
+ const hasBalanceBelowPassedValue =
98
+ options ?. value && freeBalance && freeBalance . lte ( bnToBn ( options . value ) )
99
+ if ( hasZeroBalance || hasBalanceBelowPassedValue ) {
100
+ return Promise . reject ( {
101
+ errorMessage : 'TokenBelowMinimum' ,
102
+ } )
103
+ }
104
+
83
105
// Dry run to determine required gas and potential errors
84
106
delete options . gasLimit
85
107
const dryResult = await contractCallDryRun (
@@ -155,10 +177,27 @@ export const contractTx = async (
155
177
unsub ?.( )
156
178
}
157
179
} )
158
- } catch ( e ) {
159
- console . error ( 'Error while performing transaction:' , e )
160
- // Assume transaction was cancelled by user
161
- reject ( { errorMessage : 'UserCancelled' } )
180
+ } catch ( e : any ) {
181
+ let errorMessage = 'Error'
182
+
183
+ if ( e ?. message ?. match ( / u s e r r e j e c t r e q u e s t / i) ) {
184
+ errorMessage = 'UserCancelled'
185
+ }
186
+
187
+ const errorText = e ?. toString ?.( )
188
+ const rpcErrorCode =
189
+ errorText && typeof errorText === 'string'
190
+ ? errorText . match ( / R p c E r r o r : ( \d + ) : / i) ?. [ 1 ]
191
+ : null
192
+ switch ( rpcErrorCode ) {
193
+ case '1010' :
194
+ errorMessage = 'TokenBelowMinimum'
195
+ break
196
+ default :
197
+ break
198
+ }
199
+
200
+ reject ( { errorMessage } )
162
201
}
163
202
} )
164
203
}
0 commit comments