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
42b8a5be
Commit
42b8a5be
authored
Jan 02, 2020
by
Iuri Matias
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
move udapp into blockchain module
parent
b7acc307
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
357 additions
and
400 deletions
+357
-400
settings.js
src/app/tabs/runTab/settings.js
+1
-0
blockchain.js
src/blockchain/blockchain.js
+356
-39
universalDapp.js
src/blockchain/universalDapp.js
+0
-361
No files found.
src/app/tabs/runTab/settings.js
View file @
42b8a5be
...
@@ -251,6 +251,7 @@ class SettingsUI {
...
@@ -251,6 +251,7 @@ class SettingsUI {
newAccount
()
{
newAccount
()
{
this
.
blockchain
.
newAccount
(
this
.
blockchain
.
newAccount
(
''
,
(
cb
)
=>
{
(
cb
)
=>
{
modalDialogCustom
.
promptPassphraseCreation
((
error
,
passphrase
)
=>
{
modalDialogCustom
.
promptPassphraseCreation
((
error
,
passphrase
)
=>
{
if
(
error
)
{
if
(
error
)
{
...
...
src/blockchain/blockchain.js
View file @
42b8a5be
...
@@ -2,6 +2,7 @@ const remixLib = require('remix-lib')
...
@@ -2,6 +2,7 @@ const remixLib = require('remix-lib')
const
txFormat
=
remixLib
.
execution
.
txFormat
const
txFormat
=
remixLib
.
execution
.
txFormat
const
txExecution
=
remixLib
.
execution
.
txExecution
const
txExecution
=
remixLib
.
execution
.
txExecution
const
typeConversion
=
remixLib
.
execution
.
typeConversion
const
typeConversion
=
remixLib
.
execution
.
typeConversion
const
TxRunner
=
remixLib
.
execution
.
txRunner
const
Txlistener
=
remixLib
.
execution
.
txListener
const
Txlistener
=
remixLib
.
execution
.
txListener
const
EventManager
=
remixLib
.
EventManager
const
EventManager
=
remixLib
.
EventManager
const
executionContext
=
remixLib
.
execution
.
executionContext
const
executionContext
=
remixLib
.
execution
.
executionContext
...
@@ -9,7 +10,12 @@ const ethJSUtil = require('ethereumjs-util')
...
@@ -9,7 +10,12 @@ const ethJSUtil = require('ethereumjs-util')
const
Personal
=
require
(
'web3-eth-personal'
)
const
Personal
=
require
(
'web3-eth-personal'
)
const
Web3
=
require
(
'web3'
)
const
Web3
=
require
(
'web3'
)
const
UniversalDApp
=
require
(
'./universalDapp'
)
const
async
=
require
(
'async'
)
const
{
BN
,
privateToAddress
,
isValidPrivate
,
stripHexPrefix
,
toChecksumAddress
}
=
require
(
'ethereumjs-util'
)
const
crypto
=
require
(
'crypto'
)
const
{
EventEmitter
}
=
require
(
'events'
)
const
{
resultToRemixTx
}
=
require
(
'./txResultHelper'
)
class
Blockchain
{
class
Blockchain
{
...
@@ -17,7 +23,21 @@ class Blockchain {
...
@@ -17,7 +23,21 @@ class Blockchain {
constructor
(
config
)
{
constructor
(
config
)
{
this
.
event
=
new
EventManager
()
this
.
event
=
new
EventManager
()
this
.
executionContext
=
executionContext
this
.
executionContext
=
executionContext
this
.
udapp
=
new
UniversalDApp
(
config
,
this
.
executionContext
)
this
.
events
=
new
EventEmitter
()
this
.
config
=
config
this
.
txRunner
=
new
TxRunner
({},
{
config
:
config
,
detectNetwork
:
(
cb
)
=>
{
this
.
executionContext
.
detectNetwork
(
cb
)
},
personalMode
:
()
=>
{
return
this
.
executionContext
.
getProvider
()
===
'web3'
?
this
.
config
.
get
(
'settings/personal-mode'
)
:
false
}
},
this
.
executionContext
)
this
.
accounts
=
{}
this
.
executionContext
.
event
.
register
(
'contextChanged'
,
this
.
resetEnvironment
.
bind
(
this
))
this
.
networkcallid
=
0
this
.
networkcallid
=
0
this
.
setupEvents
()
this
.
setupEvents
()
...
@@ -35,18 +55,6 @@ class Blockchain {
...
@@ -35,18 +55,6 @@ class Blockchain {
this
.
executionContext
.
event
.
register
(
'removeProvider'
,
(
name
)
=>
{
this
.
executionContext
.
event
.
register
(
'removeProvider'
,
(
name
)
=>
{
this
.
event
.
trigger
(
'removeProvider'
,
[
name
])
this
.
event
.
trigger
(
'removeProvider'
,
[
name
])
})
})
this
.
udapp
.
event
.
register
(
'initiatingTransaction'
,
(
timestamp
,
tx
,
payLoad
)
=>
{
this
.
event
.
trigger
(
'initiatingTransaction'
,
[
timestamp
,
tx
,
payLoad
])
})
this
.
udapp
.
event
.
register
(
'transactionExecuted'
,
(
error
,
from
,
to
,
data
,
call
,
txResult
,
timestamp
)
=>
{
this
.
event
.
trigger
(
'transactionExecuted'
,
[
error
,
from
,
to
,
data
,
call
,
txResult
,
timestamp
])
})
this
.
udapp
.
event
.
register
(
'transactionBroadcasted'
,
(
txhash
,
networkName
)
=>
{
this
.
event
.
trigger
(
'transactionBroadcasted'
,
[
txhash
,
networkName
])
})
}
}
async
deployContract
(
selectedContract
,
args
,
contractMetadata
,
compilerContracts
,
callbacks
,
confirmationCb
)
{
async
deployContract
(
selectedContract
,
args
,
contractMetadata
,
compilerContracts
,
callbacks
,
confirmationCb
)
{
...
@@ -74,7 +82,7 @@ class Blockchain {
...
@@ -74,7 +82,7 @@ class Blockchain {
}
}
runTransaction
(
data
,
continueCb
,
promptCb
,
confirmationCb
,
finalCb
)
{
runTransaction
(
data
,
continueCb
,
promptCb
,
confirmationCb
,
finalCb
)
{
this
.
udapp
.
runTx
(
data
,
confirmationCb
,
continueCb
,
promptCb
,
finalCb
)
this
.
runTx
(
data
,
confirmationCb
,
continueCb
,
promptCb
,
finalCb
)
}
}
createContract
(
selectedContract
,
data
,
continueCb
,
promptCb
,
confirmationCb
,
finalCb
)
{
createContract
(
selectedContract
,
data
,
continueCb
,
promptCb
,
confirmationCb
,
finalCb
)
{
...
@@ -84,7 +92,7 @@ class Blockchain {
...
@@ -84,7 +92,7 @@ class Blockchain {
data
.
contractABI
=
selectedContract
.
abi
data
.
contractABI
=
selectedContract
.
abi
}
}
this
.
udapp
.
createContract
(
data
,
confirmationCb
,
continueCb
,
promptCb
,
this
.
_
createContract
(
data
,
confirmationCb
,
continueCb
,
promptCb
,
(
error
,
txResult
)
=>
{
(
error
,
txResult
)
=>
{
if
(
error
)
{
if
(
error
)
{
return
finalCb
(
`creation of
${
selectedContract
.
name
}
errored:
${
error
}
`
)
return
finalCb
(
`creation of
${
selectedContract
.
name
}
errored:
${
error
}
`
)
...
@@ -175,7 +183,7 @@ class Blockchain {
...
@@ -175,7 +183,7 @@ class Blockchain {
}
}
getAccountBalanceForAddress
(
address
,
cb
)
{
getAccountBalanceForAddress
(
address
,
cb
)
{
return
this
.
udapp
.
getBalanceInEther
(
address
,
cb
)
return
this
.
getBalanceInEther
(
address
,
cb
)
}
}
updateNetwork
(
cb
)
{
updateNetwork
(
cb
)
{
...
@@ -196,14 +204,6 @@ class Blockchain {
...
@@ -196,14 +204,6 @@ class Blockchain {
return
this
.
executionContext
.
detectNetwork
(
cb
)
return
this
.
executionContext
.
detectNetwork
(
cb
)
}
}
newAccount
(
passphraseCb
,
cb
)
{
return
this
.
udapp
.
newAccount
(
''
,
passphraseCb
,
cb
)
}
getAccounts
(
cb
)
{
return
this
.
udapp
.
getAccounts
(
cb
)
}
isWeb3Provider
()
{
isWeb3Provider
()
{
var
isVM
=
this
.
executionContext
.
isVM
()
var
isVM
=
this
.
executionContext
.
isVM
()
var
isInjected
=
this
.
executionContext
.
getProvider
()
===
'injected'
var
isInjected
=
this
.
executionContext
.
getProvider
()
===
'injected'
...
@@ -220,7 +220,7 @@ class Blockchain {
...
@@ -220,7 +220,7 @@ class Blockchain {
if
(
isVM
)
{
if
(
isVM
)
{
const
personalMsg
=
ethJSUtil
.
hashPersonalMessage
(
Buffer
.
from
(
message
))
const
personalMsg
=
ethJSUtil
.
hashPersonalMessage
(
Buffer
.
from
(
message
))
var
privKey
=
this
.
udapp
.
accounts
[
account
].
privateKey
var
privKey
=
this
.
accounts
[
account
].
privateKey
try
{
try
{
var
rsv
=
ethJSUtil
.
ecsign
(
personalMsg
,
privKey
)
var
rsv
=
ethJSUtil
.
ecsign
(
personalMsg
,
privKey
)
var
signedData
=
ethJSUtil
.
toRpcSig
(
rsv
.
v
,
rsv
.
r
,
rsv
.
s
)
var
signedData
=
ethJSUtil
.
toRpcSig
(
rsv
.
v
,
rsv
.
r
,
rsv
.
s
)
...
@@ -259,16 +259,12 @@ class Blockchain {
...
@@ -259,16 +259,12 @@ class Blockchain {
getTxListener
(
opts
)
{
getTxListener
(
opts
)
{
opts
.
event
=
{
opts
.
event
=
{
udapp
:
this
.
udapp
.
event
udapp
:
this
.
event
}
}
const
txlistener
=
new
Txlistener
(
opts
,
this
.
executionContext
)
const
txlistener
=
new
Txlistener
(
opts
,
this
.
executionContext
)
return
txlistener
return
txlistener
}
}
startListening
(
txlistener
)
{
this
.
udapp
.
startListening
(
txlistener
)
}
runOrCallContractMethod
(
contractName
,
contractAbi
,
funABI
,
value
,
address
,
callType
,
lookupOnly
,
logMsg
,
logCallback
,
outputCb
,
confirmationCb
,
continueCb
,
promptCb
)
{
runOrCallContractMethod
(
contractName
,
contractAbi
,
funABI
,
value
,
address
,
callType
,
lookupOnly
,
logMsg
,
logCallback
,
outputCb
,
confirmationCb
,
continueCb
,
promptCb
)
{
// contractsDetails is used to resolve libraries
// contractsDetails is used to resolve libraries
txFormat
.
buildData
(
contractName
,
contractAbi
,
{},
false
,
funABI
,
callType
,
(
error
,
data
)
=>
{
txFormat
.
buildData
(
contractName
,
contractAbi
,
{},
false
,
funABI
,
callType
,
(
error
,
data
)
=>
{
...
@@ -279,7 +275,7 @@ class Blockchain {
...
@@ -279,7 +275,7 @@ class Blockchain {
logCallback
(
`
${
logMsg
}
`
)
logCallback
(
`
${
logMsg
}
`
)
}
}
if
(
funABI
.
type
===
'fallback'
)
data
.
dataHex
=
value
if
(
funABI
.
type
===
'fallback'
)
data
.
dataHex
=
value
this
.
udapp
.
callFunction
(
address
,
data
,
funABI
,
confirmationCb
,
continueCb
,
promptCb
,
(
error
,
txResult
)
=>
{
this
.
callFunction
(
address
,
data
,
funABI
,
confirmationCb
,
continueCb
,
promptCb
,
(
error
,
txResult
)
=>
{
if
(
!
error
)
{
if
(
!
error
)
{
var
isVM
=
this
.
executionContext
.
isVM
()
var
isVM
=
this
.
executionContext
.
isVM
()
if
(
isVM
)
{
if
(
isVM
)
{
...
@@ -306,22 +302,18 @@ class Blockchain {
...
@@ -306,22 +302,18 @@ class Blockchain {
},
},
(
data
,
runTxCallback
)
=>
{
(
data
,
runTxCallback
)
=>
{
// called for libraries deployment
// called for libraries deployment
this
.
udapp
.
runTx
(
data
,
confirmationCb
,
runTxCallback
)
this
.
runTx
(
data
,
confirmationCb
,
runTxCallback
)
})
})
}
}
context
()
{
return
(
this
.
executionContext
.
isVM
()
?
'memory'
:
'blockchain'
)
}
// NOTE: the config is only needed because exectuionContext.init does
// NOTE: the config is only needed because exectuionContext.init does
// if config.get('settings/always-use-vm'), we can simplify this later
// if config.get('settings/always-use-vm'), we can simplify this later
resetAndInit
(
config
,
transactionContext
)
{
resetAndInit
(
config
,
transactionContext
)
{
this
.
udapp
.
resetAPI
(
transactionContext
)
this
.
resetAPI
(
transactionContext
)
this
.
executionContext
.
init
(
config
)
this
.
executionContext
.
init
(
config
)
this
.
executionContext
.
stopListenOnLastBlock
()
this
.
executionContext
.
stopListenOnLastBlock
()
this
.
executionContext
.
listenOnLastBlock
()
this
.
executionContext
.
listenOnLastBlock
()
this
.
udapp
.
resetEnvironment
()
this
.
resetEnvironment
()
}
}
addNetwork
(
customNetwork
)
{
addNetwork
(
customNetwork
)
{
...
@@ -331,6 +323,331 @@ class Blockchain {
...
@@ -331,6 +323,331 @@ class Blockchain {
removeNetwork
(
name
)
{
removeNetwork
(
name
)
{
this
.
executionContext
.
removeProvider
(
name
)
this
.
executionContext
.
removeProvider
(
name
)
}
}
// TODO : event should be triggered by Udapp instead of TxListener
/** Listen on New Transaction. (Cannot be done inside constructor because txlistener doesn't exist yet) */
startListening
(
txlistener
)
{
txlistener
.
event
.
register
(
'newTransaction'
,
(
tx
)
=>
{
this
.
events
.
emit
(
'newTransaction'
,
tx
)
})
}
resetEnvironment
()
{
this
.
accounts
=
{}
if
(
this
.
executionContext
.
isVM
())
{
this
.
_addAccount
(
'3cd7232cd6f3fc66a57a6bedc1a8ed6c228fff0a327e169c2bcc5e869ed49511'
,
'0x56BC75E2D63100000'
)
this
.
_addAccount
(
'2ac6c190b09897cd8987869cc7b918cfea07ee82038d492abce033c75c1b1d0c'
,
'0x56BC75E2D63100000'
)
this
.
_addAccount
(
'dae9801649ba2d95a21e688b56f77905e5667c44ce868ec83f82e838712a2c7a'
,
'0x56BC75E2D63100000'
)
this
.
_addAccount
(
'd74aa6d18aa79a05f3473dd030a97d3305737cbc8337d940344345c1f6b72eea'
,
'0x56BC75E2D63100000'
)
this
.
_addAccount
(
'71975fbf7fe448e004ac7ae54cad0a383c3906055a65468714156a07385e96ce'
,
'0x56BC75E2D63100000'
)
}
// TODO: most params here can be refactored away in txRunner
this
.
txRunner
=
new
TxRunner
(
this
.
accounts
,
{
// TODO: only used to check value of doNotShowTransactionConfirmationAgain property
config
:
this
.
config
,
// TODO: to refactor, TxRunner already has access to executionContext
detectNetwork
:
(
cb
)
=>
{
this
.
executionContext
.
detectNetwork
(
cb
)
},
personalMode
:
()
=>
{
return
this
.
executionContext
.
getProvider
()
===
'web3'
?
this
.
config
.
get
(
'settings/personal-mode'
)
:
false
}
},
this
.
executionContext
)
this
.
txRunner
.
event
.
register
(
'transactionBroadcasted'
,
(
txhash
)
=>
{
this
.
executionContext
.
detectNetwork
((
error
,
network
)
=>
{
if
(
error
||
!
network
)
return
this
.
event
.
trigger
(
'transactionBroadcasted'
,
[
txhash
,
network
.
name
])
})
})
}
resetAPI
(
transactionContextAPI
)
{
this
.
transactionContextAPI
=
transactionContextAPI
}
/**
* Create a VM Account
* @param {{privateKey: string, balance: string}} newAccount The new account to create
*/
createVMAccount
(
newAccount
)
{
const
{
privateKey
,
balance
}
=
newAccount
if
(
this
.
executionContext
.
getProvider
()
!==
'vm'
)
{
throw
new
Error
(
'plugin API does not allow creating a new account through web3 connection. Only vm mode is allowed'
)
}
this
.
_addAccount
(
privateKey
,
balance
)
const
privKey
=
Buffer
.
from
(
privateKey
,
'hex'
)
return
'0x'
+
privateToAddress
(
privKey
).
toString
(
'hex'
)
}
newAccount
(
_password
,
passwordPromptCb
,
cb
)
{
if
(
!
this
.
executionContext
.
isVM
())
{
if
(
!
this
.
config
.
get
(
'settings/personal-mode'
))
{
return
cb
(
'Not running in personal mode'
)
}
passwordPromptCb
((
passphrase
)
=>
{
this
.
executionContext
.
web3
().
personal
.
newAccount
(
passphrase
,
cb
)
})
}
else
{
let
privateKey
do
{
privateKey
=
crypto
.
randomBytes
(
32
)
}
while
(
!
isValidPrivate
(
privateKey
))
this
.
_addAccount
(
privateKey
,
'0x56BC75E2D63100000'
)
cb
(
null
,
'0x'
+
privateToAddress
(
privateKey
).
toString
(
'hex'
))
}
}
/** Add an account to the list of account (only for Javascript VM) */
_addAccount
(
privateKey
,
balance
)
{
if
(
!
this
.
executionContext
.
isVM
())
{
throw
new
Error
(
'_addAccount() cannot be called in non-VM mode'
)
}
if
(
this
.
accounts
)
{
privateKey
=
Buffer
.
from
(
privateKey
,
'hex'
)
const
address
=
privateToAddress
(
privateKey
)
// FIXME: we don't care about the callback, but we should still make this proper
let
stateManager
=
this
.
executionContext
.
vm
().
stateManager
stateManager
.
getAccount
(
address
,
(
error
,
account
)
=>
{
if
(
error
)
return
console
.
log
(
error
)
account
.
balance
=
balance
||
'0xf00000000000000001'
stateManager
.
putAccount
(
address
,
account
,
function
cb
(
error
)
{
if
(
error
)
console
.
log
(
error
)
})
})
this
.
accounts
[
toChecksumAddress
(
'0x'
+
address
.
toString
(
'hex'
))]
=
{
privateKey
,
nonce
:
0
}
}
}
/** Return the list of accounts */
getAccounts
(
cb
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
const
provider
=
this
.
executionContext
.
getProvider
()
switch
(
provider
)
{
case
'vm'
:
{
if
(
!
this
.
accounts
)
{
if
(
cb
)
cb
(
'No accounts?'
)
reject
(
'No accounts?'
)
return
}
if
(
cb
)
cb
(
null
,
Object
.
keys
(
this
.
accounts
))
resolve
(
Object
.
keys
(
this
.
accounts
))
}
break
case
'web3'
:
{
if
(
this
.
config
.
get
(
'settings/personal-mode'
))
{
return
this
.
executionContext
.
web3
().
personal
.
getListAccounts
((
error
,
accounts
)
=>
{
if
(
cb
)
cb
(
error
,
accounts
)
if
(
error
)
return
reject
(
error
)
resolve
(
accounts
)
})
}
else
{
this
.
executionContext
.
web3
().
eth
.
getAccounts
((
error
,
accounts
)
=>
{
if
(
cb
)
cb
(
error
,
accounts
)
if
(
error
)
return
reject
(
error
)
resolve
(
accounts
)
})
}
}
break
case
'injected'
:
{
this
.
executionContext
.
web3
().
eth
.
getAccounts
((
error
,
accounts
)
=>
{
if
(
cb
)
cb
(
error
,
accounts
)
if
(
error
)
return
reject
(
error
)
resolve
(
accounts
)
})
}
}
})
}
/** Get the balance of an address */
getBalance
(
address
,
cb
)
{
address
=
stripHexPrefix
(
address
)
if
(
!
this
.
executionContext
.
isVM
())
{
this
.
executionContext
.
web3
().
eth
.
getBalance
(
address
,
(
err
,
res
)
=>
{
if
(
err
)
{
cb
(
err
)
}
else
{
cb
(
null
,
res
.
toString
(
10
))
}
})
}
else
{
if
(
!
this
.
accounts
)
{
return
cb
(
'No accounts?'
)
}
this
.
executionContext
.
vm
().
stateManager
.
getAccount
(
Buffer
.
from
(
address
,
'hex'
),
(
err
,
res
)
=>
{
if
(
err
)
{
cb
(
'Account not found'
)
}
else
{
cb
(
null
,
new
BN
(
res
.
balance
).
toString
(
10
))
}
})
}
}
/** Get the balance of an address, and convert wei to ether */
getBalanceInEther
(
address
,
callback
)
{
this
.
getBalance
(
address
,
(
error
,
balance
)
=>
{
if
(
error
)
{
callback
(
error
)
}
else
{
// callback(null, this.executionContext.web3().fromWei(balance, 'ether'))
callback
(
null
,
Web3
.
utils
.
fromWei
(
balance
.
toString
(
10
),
'ether'
))
}
})
}
pendingTransactionsCount
()
{
return
Object
.
keys
(
this
.
txRunner
.
pendingTxs
).
length
}
/**
* deploy the given contract
*
* @param {String} data - data to send with the transaction ( return of txFormat.buildData(...) ).
* @param {Function} callback - callback.
*/
_createContract
(
data
,
confirmationCb
,
continueCb
,
promptCb
,
callback
)
{
this
.
runTx
({
data
:
data
,
useCall
:
false
},
confirmationCb
,
continueCb
,
promptCb
,
(
error
,
txResult
)
=>
{
// see universaldapp.js line 660 => 700 to check possible values of txResult (error case)
callback
(
error
,
txResult
)
})
}
/**
* call the current given contract
*
* @param {String} to - address of the contract to call.
* @param {String} data - data to send with the transaction ( return of txFormat.buildData(...) ).
* @param {Object} funAbi - abi definition of the function to call.
* @param {Function} callback - callback.
*/
callFunction
(
to
,
data
,
funAbi
,
confirmationCb
,
continueCb
,
promptCb
,
callback
)
{
const
useCall
=
funAbi
.
stateMutability
===
'view'
||
funAbi
.
stateMutability
===
'pure'
this
.
runTx
({
to
,
data
,
useCall
},
confirmationCb
,
continueCb
,
promptCb
,
(
error
,
txResult
)
=>
{
// see universaldapp.js line 660 => 700 to check possible values of txResult (error case)
callback
(
error
,
txResult
)
})
}
context
()
{
return
(
this
.
executionContext
.
isVM
()
?
'memory'
:
'blockchain'
)
}
/**
* This function send a tx only to javascript VM or testnet, will return an error for the mainnet
* SHOULD BE TAKEN CAREFULLY!
*
* @param {Object} tx - transaction.
*/
sendTransaction
(
tx
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
this
.
executionContext
.
detectNetwork
((
error
,
network
)
=>
{
if
(
error
)
return
reject
(
error
)
if
(
network
.
name
===
'Main'
&&
network
.
id
===
'1'
)
{
return
reject
(
new
Error
(
'It is not allowed to make this action against mainnet'
))
}
this
.
silentRunTx
(
tx
,
(
error
,
result
)
=>
{
if
(
error
)
return
reject
(
error
)
try
{
resolve
(
resultToRemixTx
(
result
))
}
catch
(
e
)
{
reject
(
e
)
}
})
})
})
}
/**
* This function send a tx without alerting the user (if mainnet or if gas estimation too high).
* SHOULD BE TAKEN CAREFULLY!
*
* @param {Object} tx - transaction.
* @param {Function} callback - callback.
*/
silentRunTx
(
tx
,
cb
)
{
this
.
txRunner
.
rawRun
(
tx
,
(
network
,
tx
,
gasEstimation
,
continueTxExecution
,
cancelCb
)
=>
{
continueTxExecution
()
},
(
error
,
continueTxExecution
,
cancelCb
)
=>
{
if
(
error
)
{
cb
(
error
)
}
else
{
continueTxExecution
()
}
},
(
okCb
,
cancelCb
)
=>
{
okCb
()
},
cb
)
}
runTx
(
args
,
confirmationCb
,
continueCb
,
promptCb
,
cb
)
{
const
self
=
this
async
.
waterfall
([
function
getGasLimit
(
next
)
{
if
(
self
.
transactionContextAPI
.
getGasLimit
)
{
return
self
.
transactionContextAPI
.
getGasLimit
(
next
)
}
next
(
null
,
3000000
)
},
function
queryValue
(
gasLimit
,
next
)
{
if
(
args
.
value
)
{
return
next
(
null
,
args
.
value
,
gasLimit
)
}
if
(
args
.
useCall
||
!
self
.
transactionContextAPI
.
getValue
)
{
return
next
(
null
,
0
,
gasLimit
)
}
self
.
transactionContextAPI
.
getValue
(
function
(
err
,
value
)
{
next
(
err
,
value
,
gasLimit
)
})
},
function
getAccount
(
value
,
gasLimit
,
next
)
{
if
(
args
.
from
)
{
return
next
(
null
,
args
.
from
,
value
,
gasLimit
)
}
if
(
self
.
transactionContextAPI
.
getAddress
)
{
return
self
.
transactionContextAPI
.
getAddress
(
function
(
err
,
address
)
{
next
(
err
,
address
,
value
,
gasLimit
)
})
}
self
.
getAccounts
(
function
(
err
,
accounts
)
{
let
address
=
accounts
[
0
]
if
(
err
)
return
next
(
err
)
if
(
!
address
)
return
next
(
'No accounts available'
)
if
(
self
.
executionContext
.
isVM
()
&&
!
self
.
accounts
[
address
])
{
return
next
(
'Invalid account selected'
)
}
next
(
null
,
address
,
value
,
gasLimit
)
})
},
function
runTransaction
(
fromAddress
,
value
,
gasLimit
,
next
)
{
const
tx
=
{
to
:
args
.
to
,
data
:
args
.
data
.
dataHex
,
useCall
:
args
.
useCall
,
from
:
fromAddress
,
value
:
value
,
gasLimit
:
gasLimit
,
timestamp
:
args
.
data
.
timestamp
}
const
payLoad
=
{
funAbi
:
args
.
data
.
funAbi
,
funArgs
:
args
.
data
.
funArgs
,
contractBytecode
:
args
.
data
.
contractBytecode
,
contractName
:
args
.
data
.
contractName
,
contractABI
:
args
.
data
.
contractABI
,
linkReferences
:
args
.
data
.
linkReferences
}
let
timestamp
=
Date
.
now
()
if
(
tx
.
timestamp
)
{
timestamp
=
tx
.
timestamp
}
self
.
event
.
trigger
(
'initiatingTransaction'
,
[
timestamp
,
tx
,
payLoad
])
self
.
txRunner
.
rawRun
(
tx
,
confirmationCb
,
continueCb
,
promptCb
,
function
(
error
,
result
)
{
let
eventName
=
(
tx
.
useCall
?
'callExecuted'
:
'transactionExecuted'
)
self
.
event
.
trigger
(
eventName
,
[
error
,
tx
.
from
,
tx
.
to
,
tx
.
data
,
tx
.
useCall
,
result
,
timestamp
,
payLoad
])
if
(
error
&&
(
typeof
(
error
)
!==
'string'
))
{
if
(
error
.
message
)
error
=
error
.
message
else
{
try
{
error
=
'error: '
+
JSON
.
stringify
(
error
)
}
catch
(
e
)
{}
}
}
next
(
error
,
result
)
}
)
}
],
cb
)
}
}
}
module
.
exports
=
Blockchain
module
.
exports
=
Blockchain
src/blockchain/universalDapp.js
deleted
100644 → 0
View file @
b7acc307
const
async
=
require
(
'async'
)
const
{
BN
,
privateToAddress
,
isValidPrivate
,
stripHexPrefix
,
toChecksumAddress
}
=
require
(
'ethereumjs-util'
)
const
crypto
=
require
(
'crypto'
)
const
{
EventEmitter
}
=
require
(
'events'
)
const
remixLib
=
require
(
'remix-lib'
)
const
TxRunner
=
remixLib
.
execution
.
txRunner
const
EventManager
=
remixLib
.
EventManager
const
Web3
=
require
(
'web3'
)
const
{
resultToRemixTx
}
=
require
(
'./txResultHelper'
)
class
UniversalDApp
{
constructor
(
config
,
executionContext
)
{
this
.
events
=
new
EventEmitter
()
this
.
event
=
new
EventManager
()
// has a default for now for backwards compatability
this
.
executionContext
=
executionContext
this
.
config
=
config
this
.
txRunner
=
new
TxRunner
({},
{
config
:
config
,
detectNetwork
:
(
cb
)
=>
{
this
.
executionContext
.
detectNetwork
(
cb
)
},
personalMode
:
()
=>
{
return
this
.
executionContext
.
getProvider
()
===
'web3'
?
this
.
config
.
get
(
'settings/personal-mode'
)
:
false
}
},
this
.
executionContext
)
this
.
accounts
=
{}
this
.
executionContext
.
event
.
register
(
'contextChanged'
,
this
.
resetEnvironment
.
bind
(
this
))
}
// TODO : event should be triggered by Udapp instead of TxListener
/** Listen on New Transaction. (Cannot be done inside constructor because txlistener doesn't exist yet) */
startListening
(
txlistener
)
{
txlistener
.
event
.
register
(
'newTransaction'
,
(
tx
)
=>
{
this
.
events
.
emit
(
'newTransaction'
,
tx
)
})
}
resetEnvironment
()
{
this
.
accounts
=
{}
if
(
this
.
executionContext
.
isVM
())
{
this
.
_addAccount
(
'3cd7232cd6f3fc66a57a6bedc1a8ed6c228fff0a327e169c2bcc5e869ed49511'
,
'0x56BC75E2D63100000'
)
this
.
_addAccount
(
'2ac6c190b09897cd8987869cc7b918cfea07ee82038d492abce033c75c1b1d0c'
,
'0x56BC75E2D63100000'
)
this
.
_addAccount
(
'dae9801649ba2d95a21e688b56f77905e5667c44ce868ec83f82e838712a2c7a'
,
'0x56BC75E2D63100000'
)
this
.
_addAccount
(
'd74aa6d18aa79a05f3473dd030a97d3305737cbc8337d940344345c1f6b72eea'
,
'0x56BC75E2D63100000'
)
this
.
_addAccount
(
'71975fbf7fe448e004ac7ae54cad0a383c3906055a65468714156a07385e96ce'
,
'0x56BC75E2D63100000'
)
}
// TODO: most params here can be refactored away in txRunner
this
.
txRunner
=
new
TxRunner
(
this
.
accounts
,
{
// TODO: only used to check value of doNotShowTransactionConfirmationAgain property
config
:
this
.
config
,
// TODO: to refactor, TxRunner already has access to executionContext
detectNetwork
:
(
cb
)
=>
{
this
.
executionContext
.
detectNetwork
(
cb
)
},
personalMode
:
()
=>
{
return
this
.
executionContext
.
getProvider
()
===
'web3'
?
this
.
config
.
get
(
'settings/personal-mode'
)
:
false
}
},
this
.
executionContext
)
this
.
txRunner
.
event
.
register
(
'transactionBroadcasted'
,
(
txhash
)
=>
{
this
.
executionContext
.
detectNetwork
((
error
,
network
)
=>
{
if
(
error
||
!
network
)
return
this
.
event
.
trigger
(
'transactionBroadcasted'
,
[
txhash
,
network
.
name
])
})
})
}
resetAPI
(
transactionContextAPI
)
{
this
.
transactionContextAPI
=
transactionContextAPI
}
/**
* Create a VM Account
* @param {{privateKey: string, balance: string}} newAccount The new account to create
*/
createVMAccount
(
newAccount
)
{
const
{
privateKey
,
balance
}
=
newAccount
if
(
this
.
executionContext
.
getProvider
()
!==
'vm'
)
{
throw
new
Error
(
'plugin API does not allow creating a new account through web3 connection. Only vm mode is allowed'
)
}
this
.
_addAccount
(
privateKey
,
balance
)
const
privKey
=
Buffer
.
from
(
privateKey
,
'hex'
)
return
'0x'
+
privateToAddress
(
privKey
).
toString
(
'hex'
)
}
newAccount
(
password
,
passwordPromptCb
,
cb
)
{
if
(
!
this
.
executionContext
.
isVM
())
{
if
(
!
this
.
config
.
get
(
'settings/personal-mode'
))
{
return
cb
(
'Not running in personal mode'
)
}
passwordPromptCb
((
passphrase
)
=>
{
this
.
executionContext
.
web3
().
personal
.
newAccount
(
passphrase
,
cb
)
})
}
else
{
let
privateKey
do
{
privateKey
=
crypto
.
randomBytes
(
32
)
}
while
(
!
isValidPrivate
(
privateKey
))
this
.
_addAccount
(
privateKey
,
'0x56BC75E2D63100000'
)
cb
(
null
,
'0x'
+
privateToAddress
(
privateKey
).
toString
(
'hex'
))
}
}
/** Add an account to the list of account (only for Javascript VM) */
_addAccount
(
privateKey
,
balance
)
{
if
(
!
this
.
executionContext
.
isVM
())
{
throw
new
Error
(
'_addAccount() cannot be called in non-VM mode'
)
}
if
(
this
.
accounts
)
{
privateKey
=
Buffer
.
from
(
privateKey
,
'hex'
)
const
address
=
privateToAddress
(
privateKey
)
// FIXME: we don't care about the callback, but we should still make this proper
let
stateManager
=
this
.
executionContext
.
vm
().
stateManager
stateManager
.
getAccount
(
address
,
(
error
,
account
)
=>
{
if
(
error
)
return
console
.
log
(
error
)
account
.
balance
=
balance
||
'0xf00000000000000001'
stateManager
.
putAccount
(
address
,
account
,
function
cb
(
error
)
{
if
(
error
)
console
.
log
(
error
)
})
})
this
.
accounts
[
toChecksumAddress
(
'0x'
+
address
.
toString
(
'hex'
))]
=
{
privateKey
,
nonce
:
0
}
}
}
/** Return the list of accounts */
getAccounts
(
cb
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
const
provider
=
this
.
executionContext
.
getProvider
()
switch
(
provider
)
{
case
'vm'
:
{
if
(
!
this
.
accounts
)
{
if
(
cb
)
cb
(
'No accounts?'
)
reject
(
'No accounts?'
)
return
}
if
(
cb
)
cb
(
null
,
Object
.
keys
(
this
.
accounts
))
resolve
(
Object
.
keys
(
this
.
accounts
))
}
break
case
'web3'
:
{
if
(
this
.
config
.
get
(
'settings/personal-mode'
))
{
return
this
.
executionContext
.
web3
().
personal
.
getListAccounts
((
error
,
accounts
)
=>
{
if
(
cb
)
cb
(
error
,
accounts
)
if
(
error
)
return
reject
(
error
)
resolve
(
accounts
)
})
}
else
{
this
.
executionContext
.
web3
().
eth
.
getAccounts
((
error
,
accounts
)
=>
{
if
(
cb
)
cb
(
error
,
accounts
)
if
(
error
)
return
reject
(
error
)
resolve
(
accounts
)
})
}
}
break
case
'injected'
:
{
this
.
executionContext
.
web3
().
eth
.
getAccounts
((
error
,
accounts
)
=>
{
if
(
cb
)
cb
(
error
,
accounts
)
if
(
error
)
return
reject
(
error
)
resolve
(
accounts
)
})
}
}
})
}
/** Get the balance of an address */
getBalance
(
address
,
cb
)
{
address
=
stripHexPrefix
(
address
)
if
(
!
this
.
executionContext
.
isVM
())
{
this
.
executionContext
.
web3
().
eth
.
getBalance
(
address
,
(
err
,
res
)
=>
{
if
(
err
)
{
cb
(
err
)
}
else
{
cb
(
null
,
res
.
toString
(
10
))
}
})
}
else
{
if
(
!
this
.
accounts
)
{
return
cb
(
'No accounts?'
)
}
this
.
executionContext
.
vm
().
stateManager
.
getAccount
(
Buffer
.
from
(
address
,
'hex'
),
(
err
,
res
)
=>
{
if
(
err
)
{
cb
(
'Account not found'
)
}
else
{
cb
(
null
,
new
BN
(
res
.
balance
).
toString
(
10
))
}
})
}
}
/** Get the balance of an address, and convert wei to ether */
getBalanceInEther
(
address
,
callback
)
{
this
.
getBalance
(
address
,
(
error
,
balance
)
=>
{
if
(
error
)
{
callback
(
error
)
}
else
{
// callback(null, this.executionContext.web3().fromWei(balance, 'ether'))
callback
(
null
,
Web3
.
utils
.
fromWei
(
balance
.
toString
(
10
),
'ether'
))
}
})
}
pendingTransactionsCount
()
{
return
Object
.
keys
(
this
.
txRunner
.
pendingTxs
).
length
}
/**
* deploy the given contract
*
* @param {String} data - data to send with the transaction ( return of txFormat.buildData(...) ).
* @param {Function} callback - callback.
*/
createContract
(
data
,
confirmationCb
,
continueCb
,
promptCb
,
callback
)
{
this
.
runTx
({
data
:
data
,
useCall
:
false
},
confirmationCb
,
continueCb
,
promptCb
,
(
error
,
txResult
)
=>
{
// see universaldapp.js line 660 => 700 to check possible values of txResult (error case)
callback
(
error
,
txResult
)
})
}
/**
* call the current given contract
*
* @param {String} to - address of the contract to call.
* @param {String} data - data to send with the transaction ( return of txFormat.buildData(...) ).
* @param {Object} funAbi - abi definition of the function to call.
* @param {Function} callback - callback.
*/
callFunction
(
to
,
data
,
funAbi
,
confirmationCb
,
continueCb
,
promptCb
,
callback
)
{
const
useCall
=
funAbi
.
stateMutability
===
'view'
||
funAbi
.
stateMutability
===
'pure'
this
.
runTx
({
to
,
data
,
useCall
},
confirmationCb
,
continueCb
,
promptCb
,
(
error
,
txResult
)
=>
{
// see universaldapp.js line 660 => 700 to check possible values of txResult (error case)
callback
(
error
,
txResult
)
})
}
context
()
{
return
(
this
.
executionContext
.
isVM
()
?
'memory'
:
'blockchain'
)
}
/**
* This function send a tx only to javascript VM or testnet, will return an error for the mainnet
* SHOULD BE TAKEN CAREFULLY!
*
* @param {Object} tx - transaction.
*/
sendTransaction
(
tx
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
this
.
executionContext
.
detectNetwork
((
error
,
network
)
=>
{
if
(
error
)
return
reject
(
error
)
if
(
network
.
name
===
'Main'
&&
network
.
id
===
'1'
)
{
return
reject
(
new
Error
(
'It is not allowed to make this action against mainnet'
))
}
this
.
silentRunTx
(
tx
,
(
error
,
result
)
=>
{
if
(
error
)
return
reject
(
error
)
try
{
resolve
(
resultToRemixTx
(
result
))
}
catch
(
e
)
{
reject
(
e
)
}
})
})
})
}
/**
* This function send a tx without alerting the user (if mainnet or if gas estimation too high).
* SHOULD BE TAKEN CAREFULLY!
*
* @param {Object} tx - transaction.
* @param {Function} callback - callback.
*/
silentRunTx
(
tx
,
cb
)
{
this
.
txRunner
.
rawRun
(
tx
,
(
network
,
tx
,
gasEstimation
,
continueTxExecution
,
cancelCb
)
=>
{
continueTxExecution
()
},
(
error
,
continueTxExecution
,
cancelCb
)
=>
{
if
(
error
)
{
cb
(
error
)
}
else
{
continueTxExecution
()
}
},
(
okCb
,
cancelCb
)
=>
{
okCb
()
},
cb
)
}
runTx
(
args
,
confirmationCb
,
continueCb
,
promptCb
,
cb
)
{
const
self
=
this
async
.
waterfall
([
function
getGasLimit
(
next
)
{
if
(
self
.
transactionContextAPI
.
getGasLimit
)
{
return
self
.
transactionContextAPI
.
getGasLimit
(
next
)
}
next
(
null
,
3000000
)
},
function
queryValue
(
gasLimit
,
next
)
{
if
(
args
.
value
)
{
return
next
(
null
,
args
.
value
,
gasLimit
)
}
if
(
args
.
useCall
||
!
self
.
transactionContextAPI
.
getValue
)
{
return
next
(
null
,
0
,
gasLimit
)
}
self
.
transactionContextAPI
.
getValue
(
function
(
err
,
value
)
{
next
(
err
,
value
,
gasLimit
)
})
},
function
getAccount
(
value
,
gasLimit
,
next
)
{
if
(
args
.
from
)
{
return
next
(
null
,
args
.
from
,
value
,
gasLimit
)
}
if
(
self
.
transactionContextAPI
.
getAddress
)
{
return
self
.
transactionContextAPI
.
getAddress
(
function
(
err
,
address
)
{
next
(
err
,
address
,
value
,
gasLimit
)
})
}
self
.
getAccounts
(
function
(
err
,
accounts
)
{
let
address
=
accounts
[
0
]
if
(
err
)
return
next
(
err
)
if
(
!
address
)
return
next
(
'No accounts available'
)
if
(
self
.
executionContext
.
isVM
()
&&
!
self
.
accounts
[
address
])
{
return
next
(
'Invalid account selected'
)
}
next
(
null
,
address
,
value
,
gasLimit
)
})
},
function
runTransaction
(
fromAddress
,
value
,
gasLimit
,
next
)
{
const
tx
=
{
to
:
args
.
to
,
data
:
args
.
data
.
dataHex
,
useCall
:
args
.
useCall
,
from
:
fromAddress
,
value
:
value
,
gasLimit
:
gasLimit
,
timestamp
:
args
.
data
.
timestamp
}
const
payLoad
=
{
funAbi
:
args
.
data
.
funAbi
,
funArgs
:
args
.
data
.
funArgs
,
contractBytecode
:
args
.
data
.
contractBytecode
,
contractName
:
args
.
data
.
contractName
,
contractABI
:
args
.
data
.
contractABI
,
linkReferences
:
args
.
data
.
linkReferences
}
let
timestamp
=
Date
.
now
()
if
(
tx
.
timestamp
)
{
timestamp
=
tx
.
timestamp
}
self
.
event
.
trigger
(
'initiatingTransaction'
,
[
timestamp
,
tx
,
payLoad
])
self
.
txRunner
.
rawRun
(
tx
,
confirmationCb
,
continueCb
,
promptCb
,
function
(
error
,
result
)
{
let
eventName
=
(
tx
.
useCall
?
'callExecuted'
:
'transactionExecuted'
)
self
.
event
.
trigger
(
eventName
,
[
error
,
tx
.
from
,
tx
.
to
,
tx
.
data
,
tx
.
useCall
,
result
,
timestamp
,
payLoad
])
if
(
error
&&
(
typeof
(
error
)
!==
'string'
))
{
if
(
error
.
message
)
error
=
error
.
message
else
{
try
{
error
=
'error: '
+
JSON
.
stringify
(
error
)
}
catch
(
e
)
{}
}
}
next
(
error
,
result
)
}
)
}
],
cb
)
}
}
module
.
exports
=
UniversalDApp
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