· 8 years ago · Jan 23, 2018, 08:08 PM
1/**
2 * Use: node transaction.js AMOUNT:FROMADDR:TOADDR:TOTAG:SECRET \\
3 * eg: node transaction.js 2:rp5qN4yWgEDAK7ApLvTphHjxnSeYXd388a:rhfW7CKNPqWfZtB4DM6g6j4xPLXu1xPGv8:someSecretHere
4 * To be able to sign the transaction, the object 'wallets'
5 * below should contain the secret key for the used from-wallet.
6 */
7
8const RippleAPI = require('ripple-lib').RippleAPI
9const api = new RippleAPI({ server: 'wss://s1.ripple.com' }) // Public rippled server
10const fetch = require('node-fetch')
11
12var argv = process.argv.reverse()[0].split(':')
13if(argv.length !== 5) {
14 console.log('Invalid # arguments')
15 process.exit(1)
16}
17
18var closedLedger = 0
19var fee = 0
20var startLedger = 0
21
22/* * * * * * * * * * */
23
24 var feeLimit = 100
25 var ledgerAwait = 5
26
27 var payFrom = argv[1]
28 var payTo = argv[2]
29 var payTo_tag = parseInt(argv[3])
30 var xrpAmount = parseFloat(argv[0])
31 var _secretKey = argv[4];
32
33const wallets = {}
34wallets[_secretKey] = payFrom;
35
36 console.log('< PAY ' + xrpAmount + ' XRP FROM ' + payFrom + ' TO ' + payTo + ':' + payTo_tag)
37
38 var signed_tx = null
39 var tx_at_ledger = 0
40 var tx_result = null
41
42/* * * * * * * * * * */
43
44var _processTransaction = function () {
45 var _fee = fee
46 if(fee > feeLimit) _fee = feeLimit
47
48 console.log('>> Getting account info for: ', payFrom)
49 api.getAccountInfo(payFrom).then(function(accInfo){
50 console.log('<< [getAccountInfo] done, info: ', accInfo)
51
52 var transaction = {
53 "TransactionType" : "Payment",
54 "Account" : payFrom,
55 "Fee" : _fee+"",
56 "Destination" : payTo,
57 "DestinationTag" : payTo_tag,
58 "Amount" : (xrpAmount*1000*1000)+"",
59 "LastLedgerSequence" : closedLedger+ledgerAwait,
60 "Sequence" : accInfo.sequence
61 }
62
63 console.log('===> Transaction: ', transaction)
64
65 var txJSON = JSON.stringify(transaction)
66 var secret = Object.keys(wallets)[Object.values(wallets).indexOf(payFrom)]
67
68 if(typeof secret === 'undefined') {
69 console.log('-- ERROR RETRIEVING SECRET')
70 process.exit(1)
71 }
72
73 signed_tx = api.sign(txJSON, secret)
74 tx_at_ledger = closedLedger
75
76 console.log('===> Signed TX << ID >>: ', signed_tx.id)
77
78 console.log('-------- SUBMITTING TRANSACTION --------')
79 api.submit(signed_tx.signedTransaction).then(function(tx_data){
80 console.log(tx_data)
81
82 console.log(' >> [Tentative] Result: ', tx_data.resultCode)
83 console.log(' >> [Tentative] Message: ', tx_data.resultMessage)
84 }).catch(function(e){
85 console.log('-- ERROR SUBMITTING TRANSACTION: ', e)
86 process.exit(1)
87 })
88 })
89}
90
91var _lastClosedLedger = function (ledgerIndex) {
92 var i = parseInt(ledgerIndex)
93 if (ledgerIndex > closedLedger) {
94 if(startLedger < 1) {
95 startLedger = ledgerIndex
96 }
97
98 closedLedger = ledgerIndex
99 console.log('# LEDGER CLOSED: ', closedLedger)
100
101 if(closedLedger > startLedger + ledgerAwait + 1){
102 console.log('-- TIMEOUT AFTER # LEDGERS (+1): ', ledgerAwait)
103 process.exit(1)
104 }
105
106 api.getFee().then(function(e){
107 _fee = parseFloat(e)*1000*1000
108 if(_fee !== fee){
109 fee = _fee
110 console.log('New estimated fee: ', fee)
111 }
112 })
113
114 if(signed_tx !== null && tx_result === null && (closedLedger-tx_at_ledger) <= ledgerAwait){
115 api.getTransaction(signed_tx.id, {
116 minLedgerVersion: tx_at_ledger,
117 maxLedgerVersion: closedLedger
118 }).then(function(d){
119 console.log('<< TX RESPONSE @ L:' + (closedLedger-tx_at_ledger) + '] >> ', d)
120 tx_result = d
121 process.exit(0)
122 }).catch(function(e,x){
123 })
124 }else{
125 if(signed_tx !== null && (closedLedger-tx_at_ledger) > ledgerAwait){
126 console.log('TX FAILED')
127 process.exit(1)
128 }
129 }
130 }
131}
132
133var _bootstrap = function () {
134
135 api.connection._ws.on('message', function(m){
136 var message = JSON.parse(m)
137 if (message.type === 'ledgerClosed') {
138 _lastClosedLedger(message.ledger_index)
139 }else{
140 if (message.type !== 'response') {
141 console.log(' # < msg ', message.type)
142 }
143 }
144 })
145
146 api.connection.request({
147 command: 'subscribe',
148 accounts: Object.values(wallets)
149 })
150
151 api.connection.request({
152 command: 'subscribe',
153 streams: [ 'ledger' ]
154 })
155
156 return
157
158} /* end _bootstrap */
159
160api.on('error', (errorCode, errorMessage) => {
161 console.log(errorCode + ': ' + errorMessage)
162 process.exit(1);
163})
164api.on('connected', () => {
165 console.log('<< connected >>');
166})
167api.on('disconnected', (code) => {
168 console.log('<< disconnected >> code:', code)
169 process.exit(1);
170})
171api.connect().then(() => {
172 api.getServerInfo().then(function (server) {
173 fee = parseFloat(server.validatedLedger.baseFeeXRP)*1000*1000
174 console.log('Server base fee: ', fee)
175 _lastClosedLedger(server.validatedLedger.ledgerVersion)
176 _bootstrap()
177
178 _processTransaction()
179 })
180}).then(() => {
181}).catch(console.error)