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
4baf9bbf
Commit
4baf9bbf
authored
Jun 09, 2016
by
chriseth
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #63 from ethereum/web3-runtx
Ensure runTx always returns details about the transaction in both VM and Web3 mode
parents
c9f4197f
37e94196
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
146 additions
and
129 deletions
+146
-129
universal-dapp.js
src/universal-dapp.js
+146
-129
No files found.
src/universal-dapp.js
View file @
4baf9bbf
...
...
@@ -9,57 +9,65 @@ var EthJSBlock = require('ethereumjs-block');
var
BN
=
ethJSUtil
.
BN
;
function
UniversalDApp
(
contracts
,
options
)
{
this
.
options
=
options
||
{};
this
.
$el
=
$
(
'<div class="udapp" />'
);
this
.
contracts
=
contracts
;
this
.
renderOutputModifier
=
options
.
renderOutputModifier
||
function
(
name
,
content
)
{
return
content
;
};
var
self
=
this
;
self
.
options
=
options
||
{};
self
.
$el
=
$
(
'<div class="udapp" />'
);
self
.
contracts
=
contracts
;
self
.
renderOutputModifier
=
options
.
renderOutputModifier
||
function
(
name
,
content
)
{
return
content
;
};
this
.
web3
=
options
.
web3
;
self
.
web3
=
options
.
web3
;
if
(
options
.
mode
===
'vm'
)
{
// FIXME: use `options.vm` or `
this
.vm` consistently
// FIXME: use `options.vm` or `
self
.vm` consistently
options
.
vm
=
true
;
this
.
accounts
=
{};
self
.
accounts
=
{};
this
.
vm
=
new
EthJSVM
(
null
,
null
,
{
activatePrecompiles
:
true
,
enableHomestead
:
true
});
self
.
vm
=
new
EthJSVM
(
null
,
null
,
{
activatePrecompiles
:
true
,
enableHomestead
:
true
});
this
.
addAccount
(
'3cd7232cd6f3fc66a57a6bedc1a8ed6c228fff0a327e169c2bcc5e869ed49511'
);
this
.
addAccount
(
'2ac6c190b09897cd8987869cc7b918cfea07ee82038d492abce033c75c1b1d0c'
);
self
.
addAccount
(
'3cd7232cd6f3fc66a57a6bedc1a8ed6c228fff0a327e169c2bcc5e869ed49511'
);
self
.
addAccount
(
'2ac6c190b09897cd8987869cc7b918cfea07ee82038d492abce033c75c1b1d0c'
);
}
else
if
(
options
.
mode
!==
'web3'
)
{
throw
new
Error
(
'Either VM or Web3 mode must be selected'
);
}
}
UniversalDApp
.
prototype
.
addAccount
=
function
(
privateKey
,
balance
)
{
if
(
this
.
accounts
)
{
var
self
=
this
;
if
(
self
.
accounts
)
{
privateKey
=
new
Buffer
(
privateKey
,
'hex'
);
var
address
=
ethJSUtil
.
privateToAddress
(
privateKey
);
// FIXME: we don't care about the callback, but we should still make this proper
this
.
vm
.
stateManager
.
putAccountBalance
(
address
,
balance
||
'f00000000000000001'
,
function
cb
()
{});
self
.
vm
.
stateManager
.
putAccountBalance
(
address
,
balance
||
'f00000000000000001'
,
function
cb
()
{});
this
.
accounts
[
'0x'
+
address
.
toString
(
'hex'
)]
=
{
privateKey
:
privateKey
,
nonce
:
0
};
self
.
accounts
[
'0x'
+
address
.
toString
(
'hex'
)]
=
{
privateKey
:
privateKey
,
nonce
:
0
};
}
};
UniversalDApp
.
prototype
.
getAccounts
=
function
(
cb
)
{
if
(
!
this
.
vm
)
{
this
.
web3
.
eth
.
getAccounts
(
cb
);
var
self
=
this
;
if
(
!
self
.
vm
)
{
self
.
web3
.
eth
.
getAccounts
(
cb
);
}
else
{
if
(
!
this
.
accounts
)
{
if
(
!
self
.
accounts
)
{
return
cb
(
'No accounts?'
);
}
cb
(
null
,
Object
.
keys
(
this
.
accounts
));
cb
(
null
,
Object
.
keys
(
self
.
accounts
));
}
};
UniversalDApp
.
prototype
.
getBalance
=
function
(
address
,
cb
)
{
var
self
=
this
;
address
=
ethJSUtil
.
stripHexPrefix
(
address
);
if
(
!
this
.
vm
)
{
this
.
web3
.
eth
.
getBalance
(
address
,
function
(
err
,
res
)
{
if
(
!
self
.
vm
)
{
self
.
web3
.
eth
.
getBalance
(
address
,
function
(
err
,
res
)
{
if
(
err
)
{
cb
(
err
);
}
else
{
...
...
@@ -67,11 +75,11 @@ UniversalDApp.prototype.getBalance = function (address, cb) {
}
});
}
else
{
if
(
!
this
.
accounts
)
{
if
(
!
self
.
accounts
)
{
return
cb
(
'No accounts?'
);
}
this
.
vm
.
stateManager
.
getAccountBalance
(
new
Buffer
(
address
,
'hex'
),
function
(
err
,
res
)
{
self
.
vm
.
stateManager
.
getAccountBalance
(
new
Buffer
(
address
,
'hex'
),
function
(
err
,
res
)
{
if
(
err
)
{
cb
(
'Account not found'
);
}
else
{
...
...
@@ -82,22 +90,24 @@ UniversalDApp.prototype.getBalance = function (address, cb) {
};
UniversalDApp
.
prototype
.
render
=
function
()
{
if
(
this
.
contracts
.
length
===
0
)
{
this
.
$el
.
append
(
this
.
getABIInputForm
());
var
self
=
this
;
if
(
self
.
contracts
.
length
===
0
)
{
self
.
$el
.
append
(
self
.
getABIInputForm
());
}
else
{
for
(
var
c
in
this
.
contracts
)
{
for
(
var
c
in
self
.
contracts
)
{
var
$contractEl
=
$
(
'<div class="contract"/>'
);
if
(
this
.
contracts
[
c
].
address
)
{
this
.
getInstanceInterface
(
this
.
contracts
[
c
],
this
.
contracts
[
c
].
address
,
$contractEl
);
if
(
self
.
contracts
[
c
].
address
)
{
self
.
getInstanceInterface
(
self
.
contracts
[
c
],
self
.
contracts
[
c
].
address
,
$contractEl
);
}
else
{
var
$title
=
$
(
'<span class="title"/>'
).
text
(
this
.
contracts
[
c
].
name
);
if
(
this
.
contracts
[
c
].
bytecode
)
{
$title
.
append
(
$
(
'<div class="size"/>'
).
text
((
this
.
contracts
[
c
].
bytecode
.
length
/
2
)
+
' bytes'
));
var
$title
=
$
(
'<span class="title"/>'
).
text
(
self
.
contracts
[
c
].
name
);
if
(
self
.
contracts
[
c
].
bytecode
)
{
$title
.
append
(
$
(
'<div class="size"/>'
).
text
((
self
.
contracts
[
c
].
bytecode
.
length
/
2
)
+
' bytes'
));
}
$contractEl
.
append
(
$title
).
append
(
this
.
getCreateInterface
(
$contractEl
,
this
.
contracts
[
c
]));
$contractEl
.
append
(
$title
).
append
(
self
.
getCreateInterface
(
$contractEl
,
self
.
contracts
[
c
]));
}
this
.
$el
.
append
(
this
.
renderOutputModifier
(
this
.
contracts
[
c
].
name
,
$contractEl
));
self
.
$el
.
append
(
self
.
renderOutputModifier
(
self
.
contracts
[
c
].
name
,
$contractEl
));
}
}
var
$legend
=
$
(
'<div class="legend" />'
)
...
...
@@ -105,17 +115,18 @@ UniversalDApp.prototype.render = function () {
.
append
(
$
(
'<div class="transact"/>'
).
text
(
'Transact'
))
.
append
(
$
(
'<div class="call"/>'
).
text
(
'Call'
));
this
.
$el
.
append
(
$
(
'<div class="poweredBy" />'
)
self
.
$el
.
append
(
$
(
'<div class="poweredBy" />'
)
.
html
(
'<a href="http://github.com/d11e9/universal-dapp">Universal ÐApp</a> powered by The Blockchain'
));
this
.
$el
.
append
(
$legend
);
return
this
.
$el
;
self
.
$el
.
append
(
$legend
);
return
self
.
$el
;
};
UniversalDApp
.
prototype
.
getContractByName
=
function
(
contractName
)
{
for
(
var
c
in
this
.
contracts
)
{
if
(
this
.
contracts
[
c
].
name
===
contractName
)
{
return
this
.
contracts
[
c
];
var
self
=
this
;
for
(
var
c
in
self
.
contracts
)
{
if
(
self
.
contracts
[
c
].
name
===
contractName
)
{
return
self
.
contracts
[
c
];
}
}
return
null
;
...
...
@@ -149,12 +160,12 @@ UniversalDApp.prototype.getABIInputForm = function (cb) {
UniversalDApp
.
prototype
.
getCreateInterface
=
function
(
$container
,
contract
)
{
var
self
=
this
;
var
$createInterface
=
$
(
'<div class="create"/>'
);
if
(
this
.
options
.
removable
)
{
if
(
self
.
options
.
removable
)
{
var
$close
=
$
(
'<div class="udapp-close" />'
);
$close
.
click
(
function
()
{
self
.
$el
.
remove
();
});
$createInterface
.
append
(
$close
);
}
var
$newButton
=
this
.
getInstanceInterface
(
contract
);
var
$newButton
=
self
.
getInstanceInterface
(
contract
);
var
$atButton
=
$
(
'<button class="atAddress"/>'
).
text
(
'At Address'
).
click
(
function
()
{
self
.
clickContractAt
(
self
,
$container
.
find
(
'.createContract'
),
contract
);
});
$createInterface
.
append
(
$atButton
).
append
(
$newButton
);
return
$createInterface
;
...
...
@@ -175,7 +186,7 @@ UniversalDApp.prototype.getInstanceInterface = function (contract, address, $tar
return
1
;
}
});
var
funABI
=
this
.
getConstructorInterface
(
abi
);
var
funABI
=
self
.
getConstructorInterface
(
abi
);
var
$createInterface
=
$
(
'<div class="createContract"/>'
);
var
appendFunctions
=
function
(
address
,
$el
)
{
...
...
@@ -245,7 +256,7 @@ UniversalDApp.prototype.getInstanceInterface = function (contract, address, $tar
}
});
}
else
{
var
eventFilter
=
this
.
web3
.
eth
.
contract
(
abi
).
at
(
address
).
allEvents
();
var
eventFilter
=
self
.
web3
.
eth
.
contract
(
abi
).
at
(
address
).
allEvents
();
eventFilter
.
watch
(
parseLogs
);
}
$instance
.
append
(
$title
);
...
...
@@ -281,7 +292,7 @@ UniversalDApp.prototype.getInstanceInterface = function (contract, address, $tar
};
if
(
!
address
||
!
$target
)
{
$createInterface
.
append
(
this
.
getCallButton
({
$createInterface
.
append
(
self
.
getCallButton
({
abi
:
funABI
,
encode
:
function
(
args
)
{
var
types
=
[];
...
...
@@ -347,7 +358,7 @@ UniversalDApp.prototype.getCallButton = function (args) {
gas
=
result
.
gasUsed
.
toString
(
10
);
$gasUsed
.
html
(
'<strong>Transaction cost:</strong> '
+
gas
+
' gas. '
+
caveat
);
}
if
(
vmResult
.
gasUsed
)
{
if
(
vmResult
&&
vmResult
.
gasUsed
)
{
var
$callGasUsed
=
$
(
'<div class="gasUsed">'
);
gas
=
vmResult
.
gasUsed
.
toString
(
10
);
$callGasUsed
.
append
(
'<strong>Execution cost:</strong> '
+
gas
+
' gas.'
);
...
...
@@ -436,64 +447,71 @@ UniversalDApp.prototype.getCallButton = function (args) {
}
}
var
decodeResponse
=
function
(
response
)
{
// Only decode if there supposed to be fields
if
(
args
.
abi
.
outputs
.
length
>
0
)
{
try
{
var
i
;
var
outputTypes
=
[];
for
(
i
=
0
;
i
<
args
.
abi
.
outputs
.
length
;
i
++
)
{
outputTypes
.
push
(
args
.
abi
.
outputs
[
i
].
type
);
}
// decode data
var
decodedObj
=
ethJSABI
.
rawDecode
(
outputTypes
,
response
);
// format decoded data
decodedObj
=
ethJSABI
.
stringify
(
outputTypes
,
decodedObj
);
for
(
i
=
0
;
i
<
outputTypes
.
length
;
i
++
)
{
var
name
=
args
.
abi
.
outputs
[
i
].
name
;
if
(
name
.
length
>
0
)
{
decodedObj
[
i
]
=
outputTypes
[
i
]
+
' '
+
name
+
': '
+
decodedObj
[
i
];
}
else
{
decodedObj
[
i
]
=
outputTypes
[
i
]
+
': '
+
decodedObj
[
i
];
}
}
return
getDecodedOutput
(
decodedObj
);
}
catch
(
e
)
{
return
getDecodedOutput
(
'Failed to decode output: '
+
e
);
}
}
};
var
decoded
;
self
.
runTx
(
data
,
args
,
function
(
err
,
result
)
{
if
(
err
)
{
replaceOutput
(
$result
,
$
(
'<span/>'
).
text
(
err
).
addClass
(
'error'
));
// VM only
}
else
if
(
self
.
options
.
vm
&&
result
.
vm
.
exception
&&
result
.
vm
.
exceptionError
)
{
replaceOutput
(
$result
,
$
(
'<span/>'
).
text
(
'VM Exception: '
+
result
.
vm
.
exceptionError
).
addClass
(
'error'
));
// VM only
}
else
if
(
self
.
options
.
vm
&&
result
.
vm
.
return
===
undefined
)
{
replaceOutput
(
$result
,
$
(
'<span/>'
).
text
(
'Exception during execution.'
).
addClass
(
'error'
));
}
else
if
(
self
.
options
.
vm
&&
isConstructor
)
{
}
else
if
(
isConstructor
)
{
replaceOutput
(
$result
,
getGasUsedOutput
(
result
,
result
.
vm
));
args
.
appendFunctions
(
result
.
created
Address
);
args
.
appendFunctions
(
self
.
options
.
vm
?
result
.
createdAddress
:
result
.
contract
Address
);
}
else
if
(
self
.
options
.
vm
)
{
var
outputObj
=
'0x'
+
result
.
vm
.
return
.
toString
(
'hex'
);
clearOutput
(
$result
);
$result
.
append
(
getReturnOutput
(
outputObj
)).
append
(
getGasUsedOutput
(
result
,
result
.
vm
));
// Only decode if there supposed to be fields
if
(
args
.
abi
.
outputs
.
length
>
0
)
{
try
{
var
i
;
var
outputTypes
=
[];
for
(
i
=
0
;
i
<
args
.
abi
.
outputs
.
length
;
i
++
)
{
outputTypes
.
push
(
args
.
abi
.
outputs
[
i
].
type
);
}
// decode data
var
decodedObj
=
ethJSABI
.
rawDecode
(
outputTypes
,
result
.
vm
.
return
);
// format decoded data
decodedObj
=
ethJSABI
.
stringify
(
outputTypes
,
decodedObj
);
for
(
i
=
0
;
i
<
outputTypes
.
length
;
i
++
)
{
var
name
=
args
.
abi
.
outputs
[
i
].
name
;
if
(
name
.
length
>
0
)
{
decodedObj
[
i
]
=
outputTypes
[
i
]
+
' '
+
name
+
': '
+
decodedObj
[
i
];
}
else
{
decodedObj
[
i
]
=
outputTypes
[
i
]
+
': '
+
decodedObj
[
i
];
}
}
$result
.
append
(
getDecodedOutput
(
decodedObj
));
}
catch
(
e
)
{
$result
.
append
(
getDecodedOutput
(
'Failed to decode output: '
+
e
));
}
decoded
=
decodeResponse
(
result
.
vm
.
return
);
if
(
decoded
)
{
$result
.
append
(
decoded
);
}
}
else
if
(
args
.
abi
.
constant
&&
!
isConstructor
)
{
replaceOutput
(
$result
,
getReturnOutput
(
result
));
clearOutput
(
$result
);
$result
.
append
(
getReturnOutput
(
result
)).
append
(
getGasUsedOutput
({}));
decoded
=
decodeResponse
(
ethJSUtil
.
toBuffer
(
result
));
if
(
decoded
)
{
$result
.
append
(
decoded
);
}
}
else
{
tryTillResponse
(
self
.
web3
,
result
,
function
(
err
,
result
)
{
if
(
err
)
{
replaceOutput
(
$result
,
$
(
'<span/>'
).
text
(
err
).
addClass
(
'error'
));
}
else
if
(
isConstructor
)
{
$result
.
html
(
''
);
args
.
appendFunctions
(
result
.
contractAddress
);
}
else
{
clearOutput
(
$result
);
$result
.
append
(
getReturnOutput
(
result
)).
append
(
getGasUsedOutput
(
result
));
}
});
clearOutput
(
$result
);
$result
.
append
(
getReturnOutput
(
result
)).
append
(
getGasUsedOutput
(
result
));
}
});
};
...
...
@@ -519,7 +537,8 @@ UniversalDApp.prototype.getCallButton = function (args) {
};
UniversalDApp
.
prototype
.
linkBytecode
=
function
(
contractName
,
cb
)
{
var
bytecode
=
this
.
getContractByName
(
contractName
).
bytecode
;
var
self
=
this
;
var
bytecode
=
self
.
getContractByName
(
contractName
).
bytecode
;
if
(
bytecode
.
indexOf
(
'_'
)
<
0
)
{
return
cb
(
null
,
bytecode
);
}
...
...
@@ -528,11 +547,10 @@ UniversalDApp.prototype.linkBytecode = function (contractName, cb) {
return
cb
(
'Invalid bytecode format.'
);
}
var
libraryName
=
m
[
1
];
if
(
!
this
.
getContractByName
(
libraryName
))
{
if
(
!
self
.
getContractByName
(
libraryName
))
{
return
cb
(
'Library '
+
libraryName
+
' not found.'
);
}
var
self
=
this
;
this
.
deployLibrary
(
libraryName
,
function
(
err
,
address
)
{
self
.
deployLibrary
(
libraryName
,
function
(
err
,
address
)
{
if
(
err
)
{
return
cb
(
err
);
}
...
...
@@ -551,31 +569,24 @@ UniversalDApp.prototype.linkBytecode = function (contractName, cb) {
};
UniversalDApp
.
prototype
.
deployLibrary
=
function
(
contractName
,
cb
)
{
if
(
this
.
getContractByName
(
contractName
).
address
)
{
return
cb
(
null
,
this
.
getContractByName
(
contractName
).
address
);
}
var
self
=
this
;
var
bytecode
=
this
.
getContractByName
(
contractName
).
bytecode
;
if
(
self
.
getContractByName
(
contractName
).
address
)
{
return
cb
(
null
,
self
.
getContractByName
(
contractName
).
address
);
}
var
bytecode
=
self
.
getContractByName
(
contractName
).
bytecode
;
if
(
bytecode
.
indexOf
(
'_'
)
>=
0
)
{
this
.
linkBytecode
(
contractName
,
function
(
err
,
bytecode
)
{
self
.
linkBytecode
(
contractName
,
function
(
err
,
bytecode
)
{
if
(
err
)
cb
(
err
);
else
self
.
deployLibrary
(
contractName
,
cb
);
});
}
else
{
this
.
runTx
(
bytecode
,
{
abi
:
{
constant
:
false
},
bytecode
:
bytecode
},
function
(
err
,
result
)
{
self
.
runTx
(
bytecode
,
{
abi
:
{
constant
:
false
},
bytecode
:
bytecode
},
function
(
err
,
result
)
{
if
(
err
)
{
return
cb
(
err
);
}
if
(
self
.
options
.
vm
)
{
self
.
getContractByName
(
contractName
).
address
=
result
.
createdAddress
;
cb
(
err
,
result
.
createdAddress
);
}
else
{
tryTillResponse
(
self
.
web3
,
result
,
function
(
err
,
finalResult
)
{
if
(
err
)
return
cb
(
err
);
self
.
getContractByName
(
contractName
).
address
=
finalResult
.
contractAddress
;
cb
(
null
,
finalResult
.
contractAddress
);
});
}
var
address
=
self
.
options
.
vm
?
result
.
createdAddress
:
result
.
contractAddress
;
self
.
getContractByName
(
contractName
).
address
=
address
;
cb
(
err
,
address
);
});
}
};
...
...
@@ -585,6 +596,17 @@ UniversalDApp.prototype.clickContractAt = function (self, $output, contract) {
self
.
getInstanceInterface
(
contract
,
address
,
$output
);
};
function
tryTillResponse
(
web3
,
txhash
,
done
)
{
web3
.
eth
.
getTransactionReceipt
(
txhash
,
function
(
err
,
address
)
{
if
(
!
err
&&
!
address
)
{
// Try again with a bit of delay
setTimeout
(
function
()
{
tryTillResponse
(
web3
,
txhash
,
done
);
},
500
);
}
else
{
done
(
err
,
address
);
}
});
}
UniversalDApp
.
prototype
.
runTx
=
function
(
data
,
args
,
cb
)
{
var
self
=
this
;
var
to
=
args
.
address
;
...
...
@@ -606,30 +628,37 @@ UniversalDApp.prototype.runTx = function (data, args, cb) {
}
var
tx
;
if
(
!
this
.
vm
)
{
if
(
!
self
.
vm
)
{
tx
=
{
from
:
self
.
options
.
getAddress
?
self
.
options
.
getAddress
()
:
this
.
web3
.
eth
.
accounts
[
0
],
from
:
self
.
options
.
getAddress
?
self
.
options
.
getAddress
()
:
self
.
web3
.
eth
.
accounts
[
0
],
to
:
to
,
data
:
data
,
gas
:
gas
,
value
:
value
};
if
(
constant
&&
!
isConstructor
)
{
this
.
web3
.
eth
.
call
(
tx
,
cb
);
self
.
web3
.
eth
.
call
(
tx
,
cb
);
}
else
{
this
.
web3
.
eth
.
estimateGas
(
tx
,
function
(
err
,
resp
)
{
tx
.
gas
=
resp
;
if
(
!
err
)
{
self
.
web3
.
eth
.
sendTransaction
(
tx
,
cb
);
}
else
{
cb
(
err
,
resp
);
self
.
web3
.
eth
.
estimateGas
(
tx
,
function
(
err
,
resp
)
{
if
(
err
)
{
return
cb
(
err
,
resp
);
}
tx
.
gas
=
resp
;
self
.
web3
.
eth
.
sendTransaction
(
tx
,
function
(
err
,
resp
)
{
if
(
err
)
{
return
cb
(
err
,
resp
);
}
tryTillResponse
(
self
.
web3
,
resp
,
cb
);
});
});
}
}
else
{
try
{
var
address
=
this
.
options
.
getAddress
?
this
.
options
.
getAddress
()
:
this
.
getAccounts
()[
0
];
var
account
=
this
.
accounts
[
address
];
var
address
=
self
.
options
.
getAddress
?
self
.
options
.
getAddress
()
:
self
.
getAccounts
()[
0
];
var
account
=
self
.
accounts
[
address
];
tx
=
new
EthJSTX
({
nonce
:
new
Buffer
([
account
.
nonce
++
]),
// @todo count beyond 255
gasPrice
:
1
,
...
...
@@ -647,23 +676,11 @@ UniversalDApp.prototype.runTx = function (data, args, cb) {
transactions
:
[],
uncleHeaders
:
[]
});
this
.
vm
.
runTx
({
block
:
block
,
tx
:
tx
,
skipBalance
:
true
,
skipNonce
:
true
},
cb
);
self
.
vm
.
runTx
({
block
:
block
,
tx
:
tx
,
skipBalance
:
true
,
skipNonce
:
true
},
cb
);
}
catch
(
e
)
{
cb
(
e
,
null
);
}
}
};
function
tryTillResponse
(
web3
,
txhash
,
done
)
{
web3
.
eth
.
getTransactionReceipt
(
txhash
,
testResult
);
function
testResult
(
err
,
address
)
{
if
(
!
err
&&
!
address
)
{
setTimeout
(
function
()
{
tryTillResponse
(
web3
,
txhash
,
done
);
},
500
);
}
else
{
done
(
err
,
address
);
}
}
}
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