Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
baas-ide
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
guxukai
baas-ide
Commits
7ddc136b
Commit
7ddc136b
authored
Feb 16, 2018
by
Iuri Matias
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
move txlistener code to remix-lib
parent
c28ce1b8
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1 addition
and
366 deletions
+1
-366
app.js
src/app.js
+1
-1
txListener.js
src/app/execution/txListener.js
+0
-365
No files found.
src/app.js
View file @
7ddc136b
...
@@ -31,8 +31,8 @@ var EditorPanel = require('./app/panels/editor-panel')
...
@@ -31,8 +31,8 @@ var EditorPanel = require('./app/panels/editor-panel')
var
RighthandPanel
=
require
(
'./app/panels/righthand-panel'
)
var
RighthandPanel
=
require
(
'./app/panels/righthand-panel'
)
var
examples
=
require
(
'./app/editor/example-contracts'
)
var
examples
=
require
(
'./app/editor/example-contracts'
)
var
modalDialogCustom
=
require
(
'./app/ui/modal-dialog-custom'
)
var
modalDialogCustom
=
require
(
'./app/ui/modal-dialog-custom'
)
var
Txlistener
=
require
(
'./app/execution/txListener'
)
var
TxLogger
=
require
(
'./app/execution/txLogger'
)
var
TxLogger
=
require
(
'./app/execution/txLogger'
)
var
Txlistener
=
remixLib
.
execution
.
txListener
var
EventsDecoder
=
remixLib
.
execution
.
EventsDecoder
var
EventsDecoder
=
remixLib
.
execution
.
EventsDecoder
var
handleImports
=
require
(
'./app/compiler/compiler-imports'
)
var
handleImports
=
require
(
'./app/compiler/compiler-imports'
)
var
FileManager
=
require
(
'./app/files/fileManager'
)
var
FileManager
=
require
(
'./app/files/fileManager'
)
...
...
src/app/execution/txListener.js
deleted
100644 → 0
View file @
c28ce1b8
'use strict'
var
async
=
require
(
'async'
)
var
ethJSABI
=
require
(
'ethereumjs-abi'
)
var
ethJSUtil
=
require
(
'ethereumjs-util'
)
var
remixLib
=
require
(
'remix-lib'
)
var
EventManager
=
remixLib
.
EventManager
var
codeUtil
=
remixLib
.
util
var
executionContext
=
require
(
'../../execution-context'
)
var
txFormat
=
require
(
'./txFormat'
)
var
txHelper
=
require
(
'./txHelper'
)
/**
* poll web3 each 2s if web3
* listen on transaction executed event if VM
* attention: blocks returned by the event `newBlock` have slightly different json properties whether web3 or the VM is used
* trigger 'newBlock'
*
*/
class
TxListener
{
constructor
(
opt
)
{
this
.
event
=
new
EventManager
()
this
.
_api
=
opt
.
api
this
.
_resolvedTransactions
=
{}
this
.
_resolvedContracts
=
{}
this
.
_isListening
=
false
this
.
_listenOnNetwork
=
false
this
.
_loopId
=
null
this
.
init
()
executionContext
.
event
.
register
(
'contextChanged'
,
(
context
)
=>
{
if
(
this
.
_isListening
)
{
this
.
stopListening
()
this
.
startListening
()
}
})
opt
.
event
.
udapp
.
register
(
'callExecuted'
,
(
error
,
from
,
to
,
data
,
lookupOnly
,
txResult
)
=>
{
if
(
error
)
return
// we go for that case if
// in VM mode
// in web3 mode && listen remix txs only
if
(
!
this
.
_isListening
)
return
// we don't listen
if
(
this
.
_loopId
&&
executionContext
.
getProvider
()
!==
'vm'
)
return
// we seems to already listen on a "web3" network
var
call
=
{
from
:
from
,
to
:
to
,
input
:
data
,
hash
:
txResult
.
transactionHash
?
txResult
.
transactionHash
:
'call'
+
(
from
||
''
)
+
to
+
data
,
isCall
:
true
,
returnValue
:
executionContext
.
isVM
()
?
txResult
.
result
.
vm
.
return
:
ethJSUtil
.
toBuffer
(
txResult
.
result
),
envMode
:
executionContext
.
getProvider
()
}
addExecutionCosts
(
txResult
,
call
)
this
.
_resolveTx
(
call
,
(
error
,
resolvedData
)
=>
{
if
(
!
error
)
{
this
.
event
.
trigger
(
'newCall'
,
[
call
])
}
})
})
opt
.
event
.
udapp
.
register
(
'transactionExecuted'
,
(
error
,
from
,
to
,
data
,
lookupOnly
,
txResult
)
=>
{
if
(
error
)
return
if
(
lookupOnly
)
return
// we go for that case if
// in VM mode
// in web3 mode && listen remix txs only
if
(
!
this
.
_isListening
)
return
// we don't listen
if
(
this
.
_loopId
&&
executionContext
.
getProvider
()
!==
'vm'
)
return
// we seems to already listen on a "web3" network
executionContext
.
web3
().
eth
.
getTransaction
(
txResult
.
transactionHash
,
(
error
,
tx
)
=>
{
if
(
error
)
return
console
.
log
(
error
)
addExecutionCosts
(
txResult
,
tx
)
tx
.
envMode
=
executionContext
.
getProvider
()
tx
.
status
=
txResult
.
result
.
status
// 0x0 or 0x1
this
.
_resolve
([
tx
],
()
=>
{
})
})
})
function
addExecutionCosts
(
txResult
,
tx
)
{
if
(
txResult
&&
txResult
.
result
)
{
if
(
txResult
.
result
.
vm
)
{
tx
.
returnValue
=
txResult
.
result
.
vm
.
return
if
(
txResult
.
result
.
vm
.
gasUsed
)
tx
.
executionCost
=
txResult
.
result
.
vm
.
gasUsed
.
toString
(
10
)
}
if
(
txResult
.
result
.
gasUsed
)
tx
.
transactionCost
=
txResult
.
result
.
gasUsed
.
toString
(
10
)
}
}
}
/**
* define if txlistener should listen on the network or if only tx created from remix are managed
*
* @param {Bool} type - true if listen on the network
*/
setListenOnNetwork
(
listenOnNetwork
)
{
this
.
_listenOnNetwork
=
listenOnNetwork
if
(
this
.
_loopId
)
{
clearInterval
(
this
.
_loopId
)
}
if
(
this
.
_listenOnNetwork
)
{
this
.
_startListenOnNetwork
()
}
}
/**
* reset recorded transactions
*/
init
()
{
this
.
blocks
=
[]
this
.
lastBlock
=
null
}
/**
* start listening for incoming transactions
*
* @param {String} type - type/name of the provider to add
* @param {Object} obj - provider
*/
startListening
()
{
this
.
init
()
this
.
_isListening
=
true
if
(
this
.
_listenOnNetwork
&&
executionContext
.
getProvider
()
!==
'vm'
)
{
this
.
_startListenOnNetwork
()
}
}
/**
* stop listening for incoming transactions. do not reset the recorded pool.
*
* @param {String} type - type/name of the provider to add
* @param {Object} obj - provider
*/
stopListening
()
{
if
(
this
.
_loopId
)
{
clearInterval
(
this
.
_loopId
)
}
this
.
_loopId
=
null
this
.
_isListening
=
false
}
_startListenOnNetwork
()
{
this
.
_loopId
=
setInterval
(()
=>
{
var
currentLoopId
=
this
.
_loopId
executionContext
.
web3
().
eth
.
getBlockNumber
((
error
,
blockNumber
)
=>
{
if
(
this
.
_loopId
===
null
)
return
if
(
error
)
return
console
.
log
(
error
)
if
(
currentLoopId
===
this
.
_loopId
&&
(
!
this
.
lastBlock
||
blockNumber
>
this
.
lastBlock
))
{
if
(
!
this
.
lastBlock
)
this
.
lastBlock
=
blockNumber
-
1
var
current
=
this
.
lastBlock
+
1
this
.
lastBlock
=
blockNumber
while
(
blockNumber
>=
current
)
{
try
{
this
.
_manageBlock
(
current
)
}
catch
(
e
)
{
console
.
log
(
e
)
}
current
++
}
}
})
},
2000
)
}
_manageBlock
(
blockNumber
)
{
executionContext
.
web3
().
eth
.
getBlock
(
blockNumber
,
true
,
(
error
,
result
)
=>
{
if
(
!
error
)
{
this
.
_newBlock
(
Object
.
assign
({
type
:
'web3'
},
result
))
}
})
}
/**
* try to resolve the contract name from the given @arg address
*
* @param {String} address - contract address to resolve
* @return {String} - contract name
*/
resolvedContract
(
address
)
{
return
this
.
_resolvedContracts
[
address
]
}
/**
* try to resolve the transaction from the given @arg txHash
*
* @param {String} txHash - contract address to resolve
* @return {String} - contract name
*/
resolvedTransaction
(
txHash
)
{
return
this
.
_resolvedTransactions
[
txHash
]
}
_newBlock
(
block
)
{
this
.
blocks
.
push
(
block
)
this
.
_resolve
(
block
.
transactions
,
()
=>
{
this
.
event
.
trigger
(
'newBlock'
,
[
block
])
})
}
_resolve
(
transactions
,
callback
)
{
async
.
each
(
transactions
,
(
tx
,
cb
)
=>
{
this
.
_resolveTx
(
tx
,
(
error
,
resolvedData
)
=>
{
if
(
error
)
cb
(
error
)
if
(
resolvedData
)
{
this
.
event
.
trigger
(
'txResolved'
,
[
tx
,
resolvedData
])
}
this
.
event
.
trigger
(
'newTransaction'
,
[
tx
])
cb
()
})
},
()
=>
{
callback
()
})
}
_resolveTx
(
tx
,
cb
)
{
var
contracts
=
this
.
_api
.
contracts
()
if
(
!
contracts
)
return
cb
()
var
contractName
if
(
!
tx
.
to
||
tx
.
to
===
'0x0'
)
{
// testrpc returns 0x0 in that case
// contract creation / resolve using the creation bytes code
// if web3: we have to call getTransactionReceipt to get the created address
// if VM: created address already included
var
code
=
tx
.
input
contractName
=
this
.
_tryResolveContract
(
code
,
contracts
,
true
)
if
(
contractName
)
{
this
.
_api
.
resolveReceipt
(
tx
,
(
error
,
receipt
)
=>
{
if
(
error
)
return
cb
(
error
)
var
address
=
receipt
.
contractAddress
this
.
_resolvedContracts
[
address
]
=
contractName
var
fun
=
this
.
_resolveFunction
(
contractName
,
contracts
,
tx
,
true
)
if
(
this
.
_resolvedTransactions
[
tx
.
hash
])
{
this
.
_resolvedTransactions
[
tx
.
hash
].
contractAddress
=
address
}
return
cb
(
null
,
{
to
:
null
,
contractName
:
contractName
,
function
:
fun
,
creationAddress
:
address
})
})
return
}
return
cb
()
}
else
{
// first check known contract, resolve against the `runtimeBytecode` if not known
contractName
=
this
.
_resolvedContracts
[
tx
.
to
]
if
(
!
contractName
)
{
executionContext
.
web3
().
eth
.
getCode
(
tx
.
to
,
(
error
,
code
)
=>
{
if
(
error
)
return
cb
(
error
)
if
(
code
)
{
var
contractName
=
this
.
_tryResolveContract
(
code
,
contracts
,
false
)
if
(
contractName
)
{
this
.
_resolvedContracts
[
tx
.
to
]
=
contractName
var
fun
=
this
.
_resolveFunction
(
contractName
,
contracts
,
tx
,
false
)
return
cb
(
null
,
{
to
:
tx
.
to
,
contractName
:
contractName
,
function
:
fun
})
}
}
return
cb
()
})
return
}
if
(
contractName
)
{
var
fun
=
this
.
_resolveFunction
(
contractName
,
contracts
,
tx
,
false
)
return
cb
(
null
,
{
to
:
tx
.
to
,
contractName
:
contractName
,
function
:
fun
})
}
return
cb
()
}
}
_resolveFunction
(
contractName
,
compiledContracts
,
tx
,
isCtor
)
{
var
contract
=
txHelper
.
getContract
(
contractName
,
compiledContracts
)
if
(
!
contract
)
{
console
.
log
(
'txListener: cannot resolve '
+
contractName
)
return
}
var
abi
=
contract
.
object
.
abi
var
inputData
=
tx
.
input
.
replace
(
'0x'
,
''
)
if
(
!
isCtor
)
{
var
methodIdentifiers
=
contract
.
object
.
evm
.
methodIdentifiers
for
(
var
fn
in
methodIdentifiers
)
{
if
(
methodIdentifiers
[
fn
]
===
inputData
.
substring
(
0
,
8
))
{
var
fnabi
=
getFunction
(
abi
,
fn
)
this
.
_resolvedTransactions
[
tx
.
hash
]
=
{
contractName
:
contractName
,
to
:
tx
.
to
,
fn
:
fn
,
params
:
this
.
_decodeInputParams
(
inputData
.
substring
(
8
),
fnabi
)
}
if
(
tx
.
returnValue
)
{
this
.
_resolvedTransactions
[
tx
.
hash
].
decodedReturnValue
=
txFormat
.
decodeResponse
(
tx
.
returnValue
,
fnabi
)
}
return
this
.
_resolvedTransactions
[
tx
.
hash
]
}
}
// fallback function
this
.
_resolvedTransactions
[
tx
.
hash
]
=
{
contractName
:
contractName
,
to
:
tx
.
to
,
fn
:
'(fallback)'
,
params
:
null
}
}
else
{
var
bytecode
=
contract
.
object
.
evm
.
bytecode
.
object
var
params
=
null
if
(
bytecode
&&
bytecode
.
length
)
{
params
=
this
.
_decodeInputParams
(
inputData
.
substring
(
bytecode
.
length
),
getConstructorInterface
(
abi
))
}
this
.
_resolvedTransactions
[
tx
.
hash
]
=
{
contractName
:
contractName
,
to
:
null
,
fn
:
'(constructor)'
,
params
:
params
}
}
return
this
.
_resolvedTransactions
[
tx
.
hash
]
}
_tryResolveContract
(
codeToResolve
,
compiledContracts
,
isCreation
)
{
var
found
=
null
txHelper
.
visitContracts
(
compiledContracts
,
(
contract
)
=>
{
var
bytes
=
isCreation
?
contract
.
object
.
evm
.
bytecode
.
object
:
contract
.
object
.
evm
.
deployedBytecode
.
object
if
(
codeUtil
.
compareByteCode
(
codeToResolve
,
'0x'
+
bytes
))
{
found
=
contract
.
name
return
true
}
})
return
found
}
_decodeInputParams
(
data
,
abi
)
{
data
=
ethJSUtil
.
toBuffer
(
'0x'
+
data
)
var
inputTypes
=
[]
for
(
var
i
=
0
;
i
<
abi
.
inputs
.
length
;
i
++
)
{
inputTypes
.
push
(
abi
.
inputs
[
i
].
type
)
}
var
decoded
=
ethJSABI
.
rawDecode
(
inputTypes
,
data
)
decoded
=
ethJSABI
.
stringify
(
inputTypes
,
decoded
)
var
ret
=
{}
for
(
var
k
in
abi
.
inputs
)
{
ret
[
abi
.
inputs
[
k
].
type
+
' '
+
abi
.
inputs
[
k
].
name
]
=
decoded
[
k
]
}
return
ret
}
}
// those function will be duplicate after the merged of the compile and run tabs split
function
getConstructorInterface
(
abi
)
{
var
funABI
=
{
'name'
:
''
,
'inputs'
:
[],
'type'
:
'constructor'
,
'outputs'
:
[]
}
for
(
var
i
=
0
;
i
<
abi
.
length
;
i
++
)
{
if
(
abi
[
i
].
type
===
'constructor'
)
{
funABI
.
inputs
=
abi
[
i
].
inputs
||
[]
break
}
}
return
funABI
}
function
getFunction
(
abi
,
fnName
)
{
fnName
=
fnName
.
split
(
'('
)[
0
]
for
(
var
i
=
0
;
i
<
abi
.
length
;
i
++
)
{
if
(
abi
[
i
].
name
===
fnName
)
{
return
abi
[
i
]
}
}
return
null
}
module
.
exports
=
TxListener
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment