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
38b8de71
Commit
38b8de71
authored
Aug 08, 2017
by
yann300
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
remove unneeded code
parent
e3a83e42
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
175 additions
and
924 deletions
+175
-924
renderer.js
src/app/renderer.js
+8
-315
universal-dapp.js
src/universal-dapp.js
+167
-609
No files found.
src/app/renderer.js
View file @
38b8de71
...
...
@@ -3,73 +3,18 @@
var
$
=
require
(
'jquery'
)
var
utils
=
require
(
'./utils'
)
var
helper
=
require
(
'../lib/helper.js'
)
// -------------- styling ----------------------
var
csjs
=
require
(
'csjs-inject'
)
var
styleGuide
=
require
(
'./style-guide'
)
var
styles
=
styleGuide
()
var
css
=
csjs
`
.col2 {
width: 70%;
float: left;
}
.col1 extends
${
styles
.
titleL
}
{
width: 30%;
float: left;
}
.toggleText {
text-decoration: underline;
margin-left: 2px;
font-size: .9em;
}
.toggle {
font-size: 1.1em;
color:
${
styles
.
colors
.
blue
}
;
margin: 1em;
cursor: pointer;
font-weight: 400;
display: flex;
align-items: center;
}
.toggle:hover {
opacity: .8;
}
`
// ----------------------------------------------
function
Renderer
(
appAPI
,
compilerEvent
)
{
/**
* After refactor, the renderer is only used to render error/warning
* TODO: This don't need to be an object anymore. Simplify and just export the renderError function.
*
*/
function
Renderer
(
appAPI
)
{
this
.
appAPI
=
appAPI
var
self
=
this
compilerEvent
.
register
(
'compilationFinished'
,
this
,
function
(
success
,
data
,
source
)
{
$
(
'#output'
).
empty
()
if
(
success
)
{
self
.
contracts
(
data
,
source
)
$
(
'#header #menu .envView'
).
css
(
'color'
,
''
)
}
else
{
// envView is the `Contract` tab, as a refactor the entire envView should have his own module
$
(
'#header #menu .envView'
).
css
(
'color'
,
'#FF8B8B'
)
}
// NOTE: still need to display as there might be warnings
if
(
data
[
'error'
])
{
self
.
error
(
data
[
'error'
])
}
if
(
data
[
'errors'
])
{
data
[
'errors'
].
forEach
(
function
(
err
)
{
self
.
error
(
err
)
})
}
})
setInterval
(()
=>
{
updateAccountBalances
(
self
,
appAPI
)
},
1000
)
}
Renderer
.
prototype
.
clear
=
function
()
{
$
(
'#output'
).
empty
()
}
Renderer
.
prototype
.
error
=
function
(
message
,
container
,
options
)
{
if
(
container
===
undefined
)
return
var
self
=
this
var
opt
=
options
||
{}
if
(
!
opt
.
type
)
{
...
...
@@ -81,10 +26,7 @@ Renderer.prototype.error = function (message, container, options) {
}
else
{
$pre
=
$
(
opt
.
useSpan
?
'<span />'
:
'<pre />'
).
text
(
message
)
}
var
$error
=
$
(
'<div class="sol '
+
opt
.
type
+
'"><div class="close"><i class="fa fa-close"></i></div></div>'
).
prepend
(
$pre
)
if
(
container
===
undefined
)
{
container
=
$
(
'#output'
)
}
var
$error
=
$
(
'<div class="sol '
+
opt
.
type
+
'"><div class="close"><i class="fa fa-close"></i></div></div>'
).
prepend
(
$pre
)
container
.
append
(
$error
)
var
err
=
message
.
match
(
/^
([^
:
]
*
)
:
([
0-9
]
*
)
:
(([
0-9
]
*
)
:
)?
/
)
if
(
err
)
{
...
...
@@ -110,253 +52,4 @@ Renderer.prototype.error = function (message, container, options) {
})
}
Renderer
.
prototype
.
contracts
=
function
(
data
,
source
)
{
var
self
=
this
var
retrieveMetadataHash
=
function
(
bytecode
)
{
var
match
=
/a165627a7a72305820
([
0-9a-f
]{64})
0029$/
.
exec
(
bytecode
)
if
(
match
)
{
return
match
[
1
]
}
}
var
udappContracts
=
[]
for
(
var
contractName
in
data
.
contracts
)
{
var
contract
=
data
.
contracts
[
contractName
]
udappContracts
.
push
({
name
:
contractName
,
interface
:
contract
[
'interface'
],
bytecode
:
contract
.
bytecode
,
metadata
:
contract
.
metadata
,
metadataHash
:
contract
.
bytecode
&&
retrieveMetadataHash
(
contract
.
bytecode
)
})
}
var
tableRowItems
=
function
(
first
,
second
,
cls
)
{
second
.
get
(
0
).
classList
.
add
(
styles
.
textBoxL
)
// replace <pre> styling with textBoxL
return
$
(
'<div class="crow"/>'
)
.
addClass
(
cls
)
.
append
(
$
(
`<div class="
${
css
.
col1
}
">`
).
append
(
first
))
.
append
(
$
(
`<div class="
${
css
.
col2
}
">`
).
append
(
second
))
}
var
tableRow
=
function
(
description
,
data
)
{
return
tableRowItems
(
$
(
'<span/>'
).
text
(
description
),
$
(
`<input class="
${
css
.
col2
}
${
styles
.
textBoxL
}
" readonly="readonly"/>`
).
val
(
data
))
}
var
preRow
=
function
(
description
,
data
)
{
return
tableRowItems
(
$
(
'<span/>'
).
text
(
description
),
$
(
'<pre/>'
).
text
(
data
)
)
}
var
formatAssemblyText
=
function
(
asm
,
prefix
,
source
)
{
if
(
typeof
asm
===
typeof
''
||
asm
===
null
||
asm
===
undefined
)
{
return
prefix
+
asm
+
'
\
n'
}
var
text
=
prefix
+
'.code
\
n'
$
.
each
(
asm
[
'.code'
],
function
(
i
,
item
)
{
var
v
=
item
.
value
===
undefined
?
''
:
item
.
value
var
src
=
''
if
(
item
.
begin
!==
undefined
&&
item
.
end
!==
undefined
)
{
src
=
source
.
slice
(
item
.
begin
,
item
.
end
).
replace
(
'
\
n'
,
'
\\
n'
,
'g'
)
}
if
(
src
.
length
>
30
)
{
src
=
src
.
slice
(
0
,
30
)
+
'...'
}
if
(
item
.
name
!==
'tag'
)
{
text
+=
' '
}
text
+=
prefix
+
item
.
name
+
' '
+
v
+
'
\
t
\
t
\
t'
+
src
+
'
\
n'
})
text
+=
prefix
+
'.data
\
n'
if
(
asm
[
'.data'
])
{
$
.
each
(
asm
[
'.data'
],
function
(
i
,
item
)
{
text
+=
' '
+
prefix
+
''
+
i
+
':
\
n'
text
+=
formatAssemblyText
(
item
,
prefix
+
' '
,
source
)
})
}
return
text
}
var
getConstructorInterface
=
function
(
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
}
var
gethDeploy
=
function
(
contractName
,
jsonInterface
,
bytecode
)
{
var
code
=
''
var
funABI
=
getConstructorInterface
(
JSON
.
parse
(
jsonInterface
))
funABI
.
inputs
.
forEach
(
function
(
inp
)
{
code
+=
'var '
+
inp
.
name
+
' = /* var of type '
+
inp
.
type
+
' here */ ;
\
n'
})
contractName
=
contractName
.
replace
(
/
[
:.
/]
/g
,
'_'
)
code
+=
'var '
+
contractName
+
'Contract = web3.eth.contract('
+
jsonInterface
.
replace
(
'
\
n'
,
''
)
+
');'
+
'
\
nvar '
+
contractName
+
' = '
+
contractName
+
'Contract.new('
funABI
.
inputs
.
forEach
(
function
(
inp
)
{
code
+=
'
\
n '
+
inp
.
name
+
','
})
code
+=
'
\
n {'
+
'
\
n from: web3.eth.accounts[0], '
+
"
\
n data: '0x"
+
bytecode
+
"', "
+
"
\
n gas: '"
+
self
.
appAPI
.
currentblockGasLimit
()
+
"'"
+
'
\
n }, function (e, contract){'
+
'
\
n console.log(e, contract);'
+
"
\
n if (typeof contract.address !== 'undefined') {"
+
"
\
n console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);"
+
'
\
n }'
+
'
\
n })'
return
code
}
var
formatGasEstimates
=
function
(
data
)
{
// FIXME: the whole gasEstimates object should be nil instead
if
(
data
.
creation
===
undefined
&&
data
.
external
===
undefined
&&
data
.
internal
===
undefined
)
{
return
}
var
gasToText
=
function
(
g
)
{
return
g
===
null
?
'unknown'
:
g
}
var
text
=
''
var
fun
if
(
'creation'
in
data
)
{
text
+=
'Creation: '
+
gasToText
(
data
.
creation
[
0
])
+
' + '
+
gasToText
(
data
.
creation
[
1
])
+
'
\
n'
}
if
(
'external'
in
data
)
{
text
+=
'External:
\
n'
for
(
fun
in
data
.
external
)
{
text
+=
' '
+
fun
+
': '
+
gasToText
(
data
.
external
[
fun
])
+
'
\
n'
}
}
if
(
'internal'
in
data
)
{
text
+=
'Internal:
\
n'
for
(
fun
in
data
.
internal
)
{
text
+=
' '
+
fun
+
': '
+
gasToText
(
data
.
internal
[
fun
])
+
'
\
n'
}
}
return
text
}
var
detailsOpen
=
{}
var
getDetails
=
function
(
contract
,
source
,
contractName
)
{
var
button
=
$
(
`<div class="
${
css
.
toggle
}
"><i class="fa fa-info-circle" aria-hidden="true"></i><div class="
${
css
.
toggleText
}
">Contract details (bytecode, interface etc.)</div></div>`
)
var
details
=
$
(
'<div style="display: none;"/>'
)
if
(
contract
.
bytecode
)
{
details
.
append
(
preRow
(
'Bytecode'
,
contract
.
bytecode
))
}
details
.
append
(
preRow
(
'Interface'
,
contract
[
'interface'
]))
if
(
contract
.
bytecode
)
{
details
.
append
(
preRow
(
'Web3 deploy'
,
gethDeploy
(
contractName
.
toLowerCase
(),
contract
[
'interface'
],
contract
.
bytecode
),
'deploy'
))
// check if there's a metadata hash appended
var
metadataHash
=
retrieveMetadataHash
(
contract
.
bytecode
)
if
(
metadataHash
)
{
details
.
append
(
preRow
(
'Metadata location'
,
'bzzr://'
+
metadataHash
))
}
}
if
(
contract
.
metadata
)
{
details
.
append
(
preRow
(
'Metadata'
,
contract
.
metadata
))
}
var
funHashes
=
''
for
(
var
fun
in
contract
.
functionHashes
)
{
funHashes
+=
contract
.
functionHashes
[
fun
]
+
' '
+
fun
+
'
\
n'
}
if
(
funHashes
.
length
>
0
)
{
details
.
append
(
preRow
(
'Functions'
,
funHashes
))
}
var
gasEstimates
=
formatGasEstimates
(
contract
.
gasEstimates
)
if
(
gasEstimates
)
{
details
.
append
(
preRow
(
'Gas Estimates'
,
gasEstimates
))
}
if
(
contract
.
runtimeBytecode
&&
contract
.
runtimeBytecode
.
length
>
0
)
{
details
.
append
(
tableRow
(
'Runtime Bytecode'
,
contract
.
runtimeBytecode
))
}
if
(
contract
.
opcodes
!==
undefined
&&
contract
.
opcodes
!==
''
)
{
details
.
append
(
tableRow
(
'Opcodes'
,
contract
.
opcodes
))
}
if
(
contract
.
assembly
!==
null
)
{
details
.
append
(
preRow
(
'Assembly'
,
formatAssemblyText
(
contract
.
assembly
,
''
,
source
)))
}
button
.
click
(
function
()
{
detailsOpen
[
contractName
]
=
!
detailsOpen
[
contractName
]
details
.
toggle
()
})
if
(
detailsOpen
[
contractName
])
{
details
.
show
()
}
return
$
(
'<div class="contractDetails"/>'
).
append
(
button
).
append
(
details
)
}
var
renderOutputModifier
=
function
(
contractName
,
$contractOutput
)
{
var
contract
=
data
.
contracts
[
contractName
]
var
ctrSource
=
self
.
appAPI
.
currentCompiledSourceCode
()
if
(
ctrSource
)
{
$contractOutput
.
append
(
getDetails
(
contract
,
ctrSource
,
contractName
))
}
return
$contractOutput
}
this
.
appAPI
.
resetDapp
(
udappContracts
,
renderOutputModifier
)
var
$contractOutput
=
this
.
appAPI
.
renderDapp
()
var
$txOrigin
=
$
(
'#txorigin'
)
this
.
appAPI
.
getAccounts
(
function
(
err
,
accounts
)
{
if
(
err
)
{
self
.
error
(
err
.
message
)
}
if
(
accounts
&&
accounts
[
0
])
{
$txOrigin
.
empty
()
for
(
var
a
in
accounts
)
{
$txOrigin
.
append
(
$
(
'<option />'
).
val
(
accounts
[
a
]).
text
(
accounts
[
a
]))
}
$txOrigin
.
val
(
accounts
[
0
])
}
else
{
$txOrigin
.
val
(
'unknown'
)
}
})
$
(
'#output'
).
append
(
$contractOutput
)
$
(
'.'
+
css
.
col2
+
' input,textarea'
).
click
(
function
()
{
this
.
select
()
})
}
function
updateAccountBalances
(
self
,
appAPI
)
{
var
accounts
=
$
(
'#txorigin'
).
children
(
'option'
)
accounts
.
each
(
function
(
index
,
value
)
{
(
function
(
acc
)
{
appAPI
.
getBalance
(
accounts
[
acc
].
value
,
function
(
err
,
res
)
{
if
(
!
err
)
{
accounts
[
acc
].
innerText
=
helper
.
shortenAddress
(
accounts
[
acc
].
value
,
res
)
}
})
})(
index
)
})
}
module
.
exports
=
Renderer
src/universal-dapp.js
View file @
38b8de71
/* global
promp
t */
/* global
aler
t */
'use strict'
var
$
=
require
(
'jquery'
)
...
...
@@ -9,8 +9,11 @@ var EventManager = require('ethereum-remix').lib.EventManager
var
crypto
=
require
(
'crypto'
)
var
async
=
require
(
'async'
)
var
TxRunner
=
require
(
'./app/txRunner'
)
var
helper
=
require
(
'./lib/helper'
)
var
yo
=
require
(
'yo-yo'
)
var
txFormat
=
require
(
'./app/execution/txFormat'
)
var
txHelper
=
require
(
'./app/execution/txHelper'
)
var
txExecution
=
require
(
'./app/execution/txExecution'
)
var
helper
=
require
(
'./lib/helper'
)
// copy to copyToClipboard
const
copy
=
require
(
'clipboard-copy'
)
...
...
@@ -21,88 +24,73 @@ var styleGuide = require('./app/style-guide')
var
styles
=
styleGuide
()
var
css
=
csjs
`
html {
overflow: hidden;
}
.options {
float: left;
padding: 0.7em 0.3em;
font-size: 0.9em;
cursor: pointer;
background-color: transparent;
margin-right: 0.5em;
font-size: 1em;
}
.title extends
${
styles
.
titleBox
}
{
cursor: pointer;
background-color:
${
styles
.
colors
.
violet
}
;
justify-content: flex-start;
min-width: 400px;
}
.contract .title:before {
margin-right: 30%;
margin-left: 5%;
content: "\\25BE";
}
.contract.hidesub .title:before {
margin-right: 30%;
margin-left: 5%;
content: "\\25B8";
}
.contract.hidesub {
padding-bottom: 0;
margin: 0;
}
.contract.hidesub > *:not(.title) {
display: none;
}
.size {
margin-left: 20%;
.instanceTitleContainer {
display: flex;
align-items: center;
}
`
var
cssInstance
=
csjs
`
.title {
.title extends
${
styles
.
dropdown
}
{
display: flex;
justify-content: space-around;
min-width: 400px;
align-items: center;
margin-bottom: 1em;
padding: .3em;
font-size: .95em;
cursor: pointer;
background-color:
${
styles
.
colors
.
violet
}
;
border: 2px dotted
${
styles
.
colors
.
blue
}
;
border-radius: 5px;
justify-content: space-between;
height: 32px;
font-size: 11px;
width: 100%;
overflow: hidden;
word-break: break-word;
line-height: initial;
font-weight: bold;
background-color:
${
styles
.
colors
.
white
}
;
}
.titleText {
margin-right: 1em;
word-break: break-all;
word-break: break-word;
min-width: 230px;
}
.instance extends
${
styles
.
displayBox
}
{
padding: 10px 15px 6px 15px;
}
.instance .title:before {
content: "\\25BE";
margin-right: .5em;
margin-left: .5em;
margin-right: 5%;
}
.instance.hidesub .title:before {
content: "\\25B8";
margin-right: .5em;
margin-left: .5em;
margin-right: 5%;
}
.instance.hidesub {
padding-bottom: 0;
margin: 0;
}
.instance.hidesub > *
:not(.title)
{
.instance.hidesub > * {
display: none;
}
.copy extends
${
styles
.
button
}
{
border: 1px dotted
${
styles
.
colors
.
grey
}
;
padding: 0 .3em;
font-weight: bold;
.instance.hidesub .title {
display: flex;
}
.copy {
font-size: 13px;
cursor: pointer;
opacity: 0.8;
margin-left: 3%;
color:
${
styles
.
colors
.
black
}
;
opacity: .5;
}
.copy:hover{
opacity: .7;
opacity: 1;
}
.buttonsContainer {
margin-top: 2%;
display: flex;
}
.instanceButton {}
.closeIcon {
font-size: 10px;
position: relative;
top: -5px;
right: -2px;
}
.udappClose {
margin-left: 3%;
align-self: center;
}
`
...
...
@@ -114,12 +102,10 @@ function UniversalDApp (executionContext, options) {
var
self
=
this
self
.
options
=
options
||
{}
self
.
$el
=
$
(
'<div class="udapp" />'
)
self
.
el
=
yo
`<div class="udapp"></div>`
self
.
personalMode
=
self
.
options
.
personalMode
||
false
self
.
contracts
self
.
transactionContextAPI
var
defaultRenderOutputModifier
=
function
(
name
,
content
)
{
return
content
}
self
.
renderOutputModifier
=
defaultRenderOutputModifier
self
.
web3
=
executionContext
.
web3
()
self
.
vm
=
executionContext
.
vm
()
self
.
executionContext
=
executionContext
...
...
@@ -132,11 +118,10 @@ function UniversalDApp (executionContext, options) {
})
}
UniversalDApp
.
prototype
.
reset
=
function
(
contracts
,
transactionContextAPI
,
renderer
)
{
this
.
$el
.
empty
()
UniversalDApp
.
prototype
.
reset
=
function
(
contracts
,
transactionContextAPI
)
{
this
.
el
.
innerHTML
=
''
this
.
contracts
=
contracts
this
.
transactionContextAPI
=
transactionContextAPI
this
.
renderOutputModifier
=
renderer
this
.
accounts
=
{}
if
(
this
.
executionContext
.
isVM
())
{
this
.
_addAccount
(
'3cd7232cd6f3fc66a57a6bedc1a8ed6c228fff0a327e169c2bcc5e869ed49511'
)
...
...
@@ -234,609 +219,182 @@ UniversalDApp.prototype.getBalance = function (address, cb) {
}
}
UniversalDApp
.
prototype
.
render
=
function
()
{
var
self
=
this
// NOTE: don't display anything if there are no contracts to display
if
(
self
.
contracts
.
length
===
0
)
{
return
self
.
$el
}
var
$legend
=
$
(
'<div class="legend" />'
)
.
append
(
$
(
'<div class="publish"/>'
).
text
(
'Publish'
))
.
append
(
$
(
'<div class="attach"/>'
).
text
(
'Attach'
))
.
append
(
$
(
'<div class="transact"/>'
).
text
(
'Transact'
))
.
append
(
$
(
'<div class="payable"/>'
).
text
(
'Transact(Payable)'
))
.
append
(
$
(
'<div class="call"/>'
).
text
(
'Call'
))
self
.
$el
.
append
(
$legend
)
for
(
var
c
in
self
.
contracts
)
{
var
$contractEl
=
$
(
`<div class="contract
${
css
.
contract
}
"/>`
)
if
(
self
.
contracts
[
c
].
address
)
{
self
.
getInstanceInterface
(
self
.
contracts
[
c
],
self
.
contracts
[
c
].
address
,
$contractEl
)
}
else
{
var
$title
=
$
(
`<span class="
${
css
.
title
}
"/>`
).
text
(
self
.
contracts
[
c
].
name
)
$title
.
click
(
function
(
ev
)
{
$
(
this
).
closest
(
`.
${
css
.
contract
}
`
).
toggleClass
(
`
${
css
.
hidesub
}
`
)
})
if
(
self
.
contracts
[
c
].
bytecode
)
{
$title
.
append
(
$
(
`<div class="
${
css
.
size
}
"></div>`
).
text
((
self
.
contracts
[
c
].
bytecode
.
length
/
2
)
+
' bytes'
))
}
$contractEl
.
append
(
$title
).
append
(
self
.
getCreateInterface
(
$contractEl
,
self
.
contracts
[
c
]))
}
self
.
$el
.
append
(
self
.
renderOutputModifier
(
self
.
contracts
[
c
].
name
,
$contractEl
))
}
return
self
.
$el
}
UniversalDApp
.
prototype
.
getContractByName
=
function
(
contractName
)
{
var
self
=
this
for
(
var
c
in
self
.
contracts
)
{
if
(
self
.
contracts
[
c
].
name
===
contractName
)
{
return
self
.
contracts
[
c
]
}
}
return
null
}
UniversalDApp
.
prototype
.
getCreateInterface
=
function
(
$container
,
contract
)
{
function
remove
()
{
self
.
$el
.
remove
()
}
var
self
=
this
var
createInterface
=
yo
`<div class="create"></div>`
if
(
self
.
options
.
removable
)
{
var
close
=
yo
`<div class="udapp-close" onclick=
${
remove
}
></div>`
createInterface
.
appendChild
(
close
)
}
var
$publishButton
=
$
(
`<button class="publishContract"/>`
).
text
(
'Publish'
).
click
(
function
()
{
self
.
event
.
trigger
(
'publishContract'
,
[
contract
])
})
createInterface
.
appendChild
(
$publishButton
.
get
(
0
))
var
$atButton
=
$
(
'<button class="atAddress"/>'
).
text
(
'At Address'
).
click
(
function
()
{
self
.
clickContractAt
(
self
,
$container
.
find
(
'.createContract'
),
contract
)
})
createInterface
.
appendChild
(
$atButton
.
get
(
0
))
var
$newButton
=
self
.
getInstanceInterface
(
contract
)
if
(
!
$newButton
)
{
return
createInterface
}
createInterface
.
appendChild
(
$newButton
)
// TODO this function was named before "appendChild".
// this will render an instance: contract name, contract address, and all the public functions
// basically this has to be called for the "atAddress" (line 393) and when a contract creation succeed
// this returns a DOM element
UniversalDApp
.
prototype
.
renderInstance
=
function
(
contract
,
address
,
contractName
)
{
function
remove
()
{
$instance
.
remove
()
}
var
$instance
=
$
(
`<div class="instance
${
css
.
instance
}
"/>`
)
var
context
=
this
.
executionContext
.
isVM
()
?
'memory'
:
'blockchain'
// Only display creation interface for non-abstract contracts.
// FIXME: maybe have a flag for this in the JSON?
// FIXME: maybe fix getInstanceInterface() below for this case
if
(
contract
.
bytecode
.
length
===
0
)
{
var
$createButton
=
$newButton
.
querySelector
(
'.constructor .call'
)
address
=
(
address
.
slice
(
0
,
2
)
===
'0x'
?
''
:
'0x'
)
+
address
.
toString
(
'hex'
)
var
shortAddress
=
helper
.
shortenAddress
(
address
)
var
title
=
yo
`<div class="
${
css
.
title
}
" onclick=
${
toggleClass
}
>
<div class="
${
css
.
titleText
}
">
${
contractName
}
at
${
shortAddress
}
(
${
context
}
) </div>
<i class="fa fa-clipboard
${
css
.
copy
}
" aria-hidden="true" onclick=
${
copyToClipboard
}
title='Copy to clipboard'></i>
</div>`
// NOTE: we must show the button to have CSS properly lined up
$createButton
.
innerText
=
'Create'
$createButton
.
setAttribute
(
'disabled'
,
'disabled'
)
$createButton
.
setAttribute
(
'title'
,
'This contract does not implement all functions and thus cannot be created.'
)
if
(
this
.
options
.
removable_instances
)
{
var
close
=
yo
`<div class="
${
css
.
udappClose
}
" onclick=
${
remove
}
><i class="
${
css
.
closeIcon
}
fa fa-close" aria-hidden="true"></i></div>`
title
.
appendChild
(
close
)
}
if
((
contract
.
metadata
===
undefined
)
||
(
contract
.
metadata
.
length
===
0
))
{
$publishButton
.
attr
(
'disabled'
,
'disabled'
)
$publishButton
.
attr
(
'title'
,
'This contract does not implement all functions and thus cannot be published.'
)
function
toggleClass
()
{
$instance
.
toggleClass
(
`
${
css
.
hidesub
}
`
)
}
return
createInterface
}
UniversalDApp
.
prototype
.
getInstanceInterface
=
function
(
contract
,
address
,
$target
)
{
var
self
=
this
var
abi
=
JSON
.
parse
(
contract
.
interface
).
sort
(
function
(
a
,
b
)
{
if
(
a
.
name
>
b
.
name
)
{
return
-
1
}
else
{
return
1
}
}).
sort
(
function
(
a
,
b
)
{
if
(
a
.
constant
===
true
)
{
return
-
1
}
else
{
return
1
}
})
var
funABI
=
self
.
getConstructorInterface
(
abi
)
if
(
!
funABI
)
{
return
function
copyToClipboard
(
event
)
{
event
.
stopPropagation
()
copy
(
address
)
}
var
createInterface
=
yo
`<div class="createContract"></div>`
var
appendFunctions
=
function
(
address
,
$el
)
{
if
(
$el
)
$el
=
$el
.
get
(
0
)
function
remove
()
{
$instance
.
remove
()
}
var
$instance
=
$
(
`<div class="instance
${
cssInstance
.
instance
}
"/>`
)
if
(
self
.
options
.
removable_instances
)
{
var
close
=
yo
`<div class="udapp-close" onclick=
${
remove
}
></div>`
$instance
.
get
(
0
).
appendChild
(
close
)
}
var
context
=
self
.
executionContext
.
isVM
()
?
'memory'
:
'blockchain'
address
=
(
address
.
slice
(
0
,
2
)
===
'0x'
?
''
:
'0x'
)
+
address
.
toString
(
'hex'
)
var
shortAddress
=
helper
.
shortenAddress
(
address
)
var
title
=
yo
`
<div class="
${
cssInstance
.
title
}
" onclick=
${
toggleClass
}
>
<div class="
${
cssInstance
.
titleText
}
">
${
contract
.
name
}
at
${
shortAddress
}
(
${
context
}
) </div>
<div class="
${
cssInstance
.
copy
}
" onclick=
${
copyToClipboard
}
> <i class="fa fa-clipboard" aria-hidden="true"></i> Copy address </div>
</div>
`
function
toggleClass
()
{
$instance
.
toggleClass
(
`
${
cssInstance
.
hidesub
}
`
)
}
function
copyToClipboard
(
event
)
{
event
.
stopPropagation
()
copy
(
address
)
}
var
$events
=
$
(
'<div class="events"/>'
)
var
parseLogs
=
function
(
err
,
response
)
{
if
(
err
)
{
return
}
var
$events
=
$
(
'<div class="events"/>'
)
var
$event
=
$
(
'<div class="event" />'
)
var
close
=
yo
`<div class="udapp-close" onclick=
${
remove
}
></div>`
function
remove
()
{
$event
.
remove
()
}
$event
.
append
(
$
(
'<span class="name"/>'
).
text
(
response
.
event
))
.
append
(
$
(
'<span class="args" />'
).
text
(
JSON
.
stringify
(
response
.
args
,
null
,
2
)))
$event
.
get
(
0
).
appendChild
(
close
)
$events
.
append
(
$event
)
var
parseLogs
=
function
(
err
,
response
)
{
if
(
err
)
{
return
}
if
(
self
.
executionContext
.
isVM
())
{
// FIXME: support indexed events
var
eventABI
=
{}
var
$event
=
$
(
'<div class="event" />'
)
$
.
each
(
abi
,
function
(
i
,
funABI
)
{
if
(
funABI
.
type
!==
'event'
)
{
return
}
var
hash
=
ethJSABI
.
eventID
(
funABI
.
name
,
funABI
.
inputs
.
map
(
function
(
item
)
{
return
item
.
type
}))
eventABI
[
hash
.
toString
(
'hex'
)]
=
{
event
:
funABI
.
name
,
inputs
:
funABI
.
inputs
}
})
var
close
=
yo
`<div class="udapp-close" onclick=
${
remove
}
><i class="
${
css
.
closeIcon
}
fa fa-close" aria-hidden="true"></i></div>`
function
remove
()
{
$event
.
remove
()
}
self
.
vm
.
on
(
'afterTx'
,
function
(
response
)
{
for
(
var
i
in
response
.
vm
.
logs
)
{
// [address, topics, mem]
var
log
=
response
.
vm
.
logs
[
i
]
var
event
var
decoded
try
{
var
abi
=
eventABI
[
log
[
1
][
0
].
toString
(
'hex'
)]
event
=
abi
.
event
var
types
=
abi
.
inputs
.
map
(
function
(
item
)
{
return
item
.
type
})
decoded
=
ethJSABI
.
rawDecode
(
types
,
log
[
2
])
decoded
=
ethJSABI
.
stringify
(
types
,
decoded
)
}
catch
(
e
)
{
decoded
=
'0x'
+
log
[
2
].
toString
(
'hex'
)
}
parseLogs
(
null
,
{
event
:
event
,
args
:
decoded
})
}
})
}
else
{
var
eventFilter
=
self
.
web3
.
eth
.
contract
(
abi
).
at
(
address
).
allEvents
()
eventFilter
.
watch
(
parseLogs
)
}
$instance
.
get
(
0
).
appendChild
(
title
)
// Add the fallback function
var
fallback
=
self
.
getFallbackInterface
(
abi
)
if
(
fallback
)
{
$instance
.
append
(
self
.
getCallButton
({
abi
:
fallback
,
encode
:
function
(
args
)
{
return
''
},
address
:
address
}))
}
$event
.
append
(
$
(
'<span class="name"/>'
).
text
(
response
.
event
))
.
append
(
$
(
'<span class="args" />'
).
text
(
JSON
.
stringify
(
response
.
args
,
null
,
2
)))
$event
.
get
(
0
).
appendChild
(
close
)
$events
.
append
(
$event
)
}
var
abi
=
txHelper
.
sortAbiFunction
(
contract
)
if
(
this
.
executionContext
.
isVM
())
{
// FIXME: support indexed events
var
eventABI
=
{}
$
.
each
(
abi
,
function
(
i
,
funABI
)
{
if
(
funABI
.
type
!==
'
function
'
)
{
if
(
funABI
.
type
!==
'
event
'
)
{
return
}
// @todo getData cannot be used with overloaded functions
$instance
.
append
(
self
.
getCallButton
({
abi
:
funABI
,
encode
:
function
(
args
)
{
var
types
=
[]
for
(
var
i
=
0
;
i
<
funABI
.
inputs
.
length
;
i
++
)
{
types
.
push
(
funABI
.
inputs
[
i
].
type
)
}
return
Buffer
.
concat
([
ethJSABI
.
methodID
(
funABI
.
name
,
types
),
ethJSABI
.
rawEncode
(
types
,
args
)
]).
toString
(
'hex'
)
},
address
:
address
}))
var
hash
=
ethJSABI
.
eventID
(
funABI
.
name
,
funABI
.
inputs
.
map
(
function
(
item
)
{
return
item
.
type
}))
eventABI
[
hash
.
toString
(
'hex'
)]
=
{
event
:
funABI
.
name
,
inputs
:
funABI
.
inputs
}
})
$el
=
$el
||
createInterface
$el
.
appendChild
(
$instance
.
append
(
$events
).
get
(
0
))
}
this
.
vm
.
on
(
'afterTx'
,
function
(
response
)
{
for
(
var
i
in
response
.
vm
.
logs
)
{
// [address, topics, mem]
var
log
=
response
.
vm
.
logs
[
i
]
var
event
var
decoded
if
(
!
address
||
!
$target
)
{
createInterface
.
appendChild
(
self
.
getCallButton
({
abi
:
funABI
,
encode
:
function
(
args
)
{
var
types
=
[]
for
(
var
i
=
0
;
i
<
funABI
.
inputs
.
length
;
i
++
)
{
types
.
push
(
funABI
.
inputs
[
i
].
type
)
try
{
var
abi
=
eventABI
[
log
[
1
][
0
].
toString
(
'hex'
)]
event
=
abi
.
event
var
types
=
abi
.
inputs
.
map
(
function
(
item
)
{
return
item
.
type
})
decoded
=
ethJSABI
.
rawDecode
(
types
,
log
[
2
])
decoded
=
ethJSABI
.
stringify
(
types
,
decoded
)
}
catch
(
e
)
{
decoded
=
'0x'
+
log
[
2
].
toString
(
'hex'
)
}
// NOTE: the caller will concatenate the bytecode and this
// it could be done here too for consistency
return
ethJSABI
.
rawEncode
(
types
,
args
).
toString
(
'hex'
)
},
contractName
:
contract
.
name
,
bytecode
:
contract
.
bytecode
,
appendFunctions
:
appendFunctions
}).
get
(
0
))
parseLogs
(
null
,
{
event
:
event
,
args
:
decoded
})
}
})
}
else
{
appendFunctions
(
address
,
$target
)
var
eventFilter
=
this
.
web3
.
eth
.
contract
(
abi
).
at
(
address
).
allEvents
()
eventFilter
.
watch
(
parseLogs
)
}
return
createInterface
}
$instance
.
get
(
0
).
appendChild
(
title
)
UniversalDApp
.
prototype
.
getConstructorInterface
=
function
(
abi
)
{
for
(
var
i
=
0
;
i
<
abi
.
length
;
i
++
)
{
if
(
abi
[
i
].
type
===
'constructor'
)
{
return
abi
[
i
]
}
// Add the fallback function
var
fallback
=
txHelper
.
getFallbackInterface
(
abi
)
if
(
fallback
)
{
$instance
.
append
(
this
.
getCallButton
({
funABI
:
fallback
,
address
:
address
,
contractAbi
:
abi
}))
}
return
{
'type'
:
'constructor'
,
'payable'
:
false
,
'inputs'
:
[]
}
}
UniversalDApp
.
prototype
.
getFallbackInterface
=
function
(
abi
)
{
for
(
var
i
=
0
;
i
<
abi
.
length
;
i
++
)
{
if
(
abi
[
i
].
type
===
'fallback'
)
{
return
abi
[
i
]
$
.
each
(
abi
,
(
i
,
funABI
)
=>
{
if
(
funABI
.
type
!==
'function'
)
{
return
}
}
// @todo getData cannot be used with overloaded functions
$instance
.
append
(
this
.
getCallButton
({
funABI
:
funABI
,
address
:
address
,
contractAbi
:
abi
}))
})
$instance
.
append
(
$events
)
return
$instance
.
get
(
0
)
}
// TODO this is used by renderInstance when a new instance is displayed.
// this returns a DOM element.
UniversalDApp
.
prototype
.
getCallButton
=
function
(
args
)
{
var
self
=
this
// args.abi, args.encode, args.bytecode [constr only], args.address [fun only]
// args.contractName [constr only], args.appendFunctions [constr only]
var
isConstructor
=
args
.
bytecode
!==
undefined
var
lookupOnly
=
(
args
.
abi
.
constant
&&
!
isConstructor
)
// args.funABI, args.address [fun only]
// args.contractName [constr only]
var
lookupOnly
=
args
.
funABI
.
constant
var
inputs
=
''
if
(
args
.
abi
.
inputs
)
{
$
.
each
(
args
.
abi
.
inputs
,
function
(
i
,
inp
)
{
if
(
inputs
!==
''
)
{
inputs
+=
', '
}
inputs
+=
inp
.
type
+
' '
+
inp
.
name
})
if
(
args
.
funABI
.
inputs
)
{
inputs
=
txHelper
.
inputParametersDeclarationToString
(
args
.
funABI
.
inputs
)
}
var
inputField
=
$
(
'<input/>'
).
attr
(
'placeholder'
,
inputs
).
attr
(
'title'
,
inputs
)
var
$outputOverride
=
$
(
'<div class="value" />'
)
var
outputSpan
=
$
(
'<div class="output"/>'
)
var
getReturnOutput
=
function
(
result
)
{
var
returnName
=
lookupOnly
?
'Value'
:
'Result'
var
returnCls
=
lookupOnly
?
'value'
:
'returned'
return
$
(
'<div class="'
+
returnCls
+
'">'
).
html
(
'<strong>'
+
returnName
+
':</strong> '
+
JSON
.
stringify
(
result
,
null
,
2
))
}
var
getDebugTransaction
=
function
(
result
)
{
var
$debugTx
=
$
(
'<div class="debugTx">'
)
var
$button
=
$
(
'<button title="Launch Debugger" class="debug"><i class="fa fa-bug"></i> Launch debugger </button>'
)
$button
.
click
(
function
()
{
self
.
event
.
trigger
(
'debugRequested'
,
[
result
])
})
$debugTx
.
append
(
$button
)
return
$debugTx
}
var
getDebugCall
=
function
(
result
)
{
var
$debugTx
=
$
(
'<div class="debugCall">'
)
var
$button
=
$
(
'<button title="Launch Debugger" class="debug"><i class="fa fa-bug"></i> Launch debugger </button>'
)
$button
.
click
(
function
()
{
self
.
event
.
trigger
(
'debugRequested'
,
[
result
])
})
$debugTx
.
append
(
$button
)
return
$debugTx
}
var
getGasUsedOutput
=
function
(
result
,
vmResult
)
{
var
$gasUsed
=
$
(
'<div class="gasUsed"></div>'
)
var
caveat
=
lookupOnly
?
'<em>(<span class="caveat" title="Cost only applies when called by a contract">caveat</span>)</em>'
:
''
var
gas
if
(
result
.
gasUsed
)
{
gas
=
result
.
gasUsed
.
toString
(
10
)
$gasUsed
.
html
(
'<strong>Transaction cost:</strong> '
+
gas
+
' gas. '
+
caveat
)
}
if
(
vmResult
&&
vmResult
.
gasUsed
)
{
var
$callGasUsed
=
$
(
'<div class="gasUsed">'
)
gas
=
vmResult
.
gasUsed
.
toString
(
10
)
$callGasUsed
.
append
(
'<strong>Execution cost:</strong> '
+
gas
+
' gas.'
)
$gasUsed
.
append
(
$callGasUsed
)
}
return
$gasUsed
}
var
getDecodedOutput
=
function
(
result
)
{
var
$decoded
if
(
Array
.
isArray
(
result
))
{
$decoded
=
$
(
'<ol>'
)
for
(
var
i
=
0
;
i
<
result
.
length
;
i
++
)
{
$decoded
.
append
(
$
(
'<li>'
).
text
(
result
[
i
]))
}
}
else
{
$decoded
=
result
}
return
$
(
'<div class="decoded">'
).
html
(
'<strong>Decoded:</strong> '
).
append
(
$decoded
)
}
var
getOutput
=
function
()
{
var
$result
=
$
(
'<div class="result" />'
)
var
close
=
yo
`<div class="udapp-close" onclick=
${
remove
}
></div>`
function
remove
()
{
$result
.
remove
()
}
$result
.
get
(
0
).
appendChild
(
close
)
return
$result
}
var
clearOutput
=
function
(
$result
)
{
$
(
':not(.udapp-close)'
,
$result
).
remove
()
}
var
replaceOutput
=
function
(
$result
,
message
)
{
clearOutput
(
$result
)
$result
.
append
(
message
)
}
var
handleCallButtonClick
=
function
(
ev
,
$result
)
{
if
(
!
$result
)
{
$result
=
getOutput
()
if
(
lookupOnly
&&
!
inputs
.
length
)
{
$outputOverride
.
empty
().
append
(
$result
)
}
else
{
outputSpan
.
append
(
$result
)
}
}
var
funArgs
=
''
try
{
funArgs
=
$
.
parseJSON
(
'['
+
inputField
.
val
()
+
']'
)
}
catch
(
e
)
{
replaceOutput
(
$result
,
$
(
'<span/>'
).
text
(
'Error encoding arguments: '
+
e
))
return
}
var
data
=
''
if
(
!
isConstructor
||
funArgs
.
length
>
0
)
{
try
{
data
=
args
.
encode
(
funArgs
)
}
catch
(
e
)
{
replaceOutput
(
$result
,
$
(
'<span/>'
).
text
(
'Error encoding arguments: '
+
e
))
return
}
}
if
(
data
.
slice
(
0
,
9
)
===
'undefined'
)
{
data
=
data
.
slice
(
9
)
}
if
(
data
.
slice
(
0
,
2
)
===
'0x'
)
{
data
=
data
.
slice
(
2
)
}
replaceOutput
(
$result
,
$
(
'<span>Waiting for transaction to be mined...</span>'
))
if
(
isConstructor
)
{
if
(
args
.
bytecode
.
indexOf
(
'_'
)
>=
0
)
{
replaceOutput
(
$result
,
$
(
'<span>Deploying and linking required libraries...</span>'
))
self
.
linkBytecode
(
args
.
contractName
,
function
(
err
,
bytecode
)
{
if
(
err
)
{
replaceOutput
(
$result
,
$
(
'<span/>'
).
text
(
'Error deploying required libraries: '
+
err
))
}
else
{
args
.
bytecode
=
bytecode
handleCallButtonClick
(
ev
,
$result
)
}
})
return
}
else
{
data
=
args
.
bytecode
+
data
}
}
var
decodeResponse
=
function
(
response
)
{
// Only decode if there supposed to be fields
if
(
args
.
abi
.
outputs
&&
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
({
to
:
args
.
address
,
data
:
data
,
useCall
:
lookupOnly
},
function
(
err
,
txResult
)
{
self
.
event
.
trigger
(
'transactionExecuted'
,
[
args
.
address
,
data
,
lookupOnly
,
txResult
])
if
(
!
txResult
)
{
replaceOutput
(
$result
,
$
(
'<span/>'
).
text
(
'callback contain no result '
+
err
).
addClass
(
'error'
))
return
}
var
result
=
txResult
.
result
if
(
err
)
{
replaceOutput
(
$result
,
$
(
'<span/>'
).
text
(
err
).
addClass
(
'error'
))
// VM only
}
else
if
(
self
.
executionContext
.
isVM
()
&&
result
.
vm
.
exception
===
0
&&
result
.
vm
.
exceptionError
)
{
replaceOutput
(
$result
,
$
(
'<span/>'
).
text
(
'Exception during execution. ('
+
result
.
vm
.
exceptionError
+
'). Please debug the transaction for more information.'
).
addClass
(
'error'
))
$result
.
append
(
getDebugTransaction
(
txResult
))
// VM only
}
else
if
(
self
.
executionContext
.
isVM
()
&&
result
.
vm
.
return
===
undefined
)
{
replaceOutput
(
$result
,
$
(
'<span/>'
).
text
(
'Exception during execution. Please debug the transaction for more information.'
).
addClass
(
'error'
))
$result
.
append
(
getDebugTransaction
(
txResult
))
}
else
if
(
isConstructor
)
{
replaceOutput
(
$result
,
getGasUsedOutput
(
result
,
result
.
vm
))
$result
.
append
(
getDebugTransaction
(
txResult
))
args
.
appendFunctions
(
self
.
executionContext
.
isVM
()
?
result
.
createdAddress
:
result
.
contractAddress
)
}
else
if
(
self
.
executionContext
.
isVM
())
{
var
outputObj
=
'0x'
+
result
.
vm
.
return
.
toString
(
'hex'
)
clearOutput
(
$result
)
$result
.
append
(
getReturnOutput
(
outputObj
)).
append
(
getGasUsedOutput
(
result
,
result
.
vm
))
decoded
=
decodeResponse
(
result
.
vm
.
return
)
if
(
decoded
)
{
$result
.
append
(
decoded
)
}
if
(
lookupOnly
)
{
$result
.
append
(
getDebugCall
(
txResult
))
}
else
{
$result
.
append
(
getDebugTransaction
(
txResult
))
}
}
else
if
(
lookupOnly
)
{
clearOutput
(
$result
)
$result
.
append
(
getReturnOutput
(
result
)).
append
(
getGasUsedOutput
({}))
decoded
=
decodeResponse
(
ethJSUtil
.
toBuffer
(
result
))
if
(
decoded
)
{
$result
.
append
(
decoded
)
}
}
else
{
clearOutput
(
$result
)
$result
.
append
(
getReturnOutput
(
result
)).
append
(
getGasUsedOutput
(
result
))
$result
.
append
(
getDebugTransaction
(
txResult
))
}
})
}
var
title
if
(
isConstructor
)
{
title
=
'Create'
}
else
if
(
args
.
abi
.
name
)
{
title
=
args
.
abi
.
name
if
(
args
.
funABI
.
name
)
{
title
=
args
.
funABI
.
name
}
else
{
title
=
'(fallback)'
}
var
button
=
$
(
'<button />'
)
var
button
=
$
(
`<button class="
${
css
.
instanceButton
}
"/>`
)
.
addClass
(
'call'
)
.
attr
(
'title'
,
title
)
.
text
(
title
)
.
click
(
handleCallButtonClick
)
.
click
(()
=>
{
txFormat
.
buildData
(
args
.
contractAbi
,
self
.
contracts
,
false
,
args
.
funABI
,
inputField
.
val
(),
self
,
self
.
executionContext
,
(
error
,
data
)
=>
{
if
(
!
error
)
{
txExecution
.
callFunction
(
args
.
address
,
data
,
args
.
funABI
,
self
,
(
error
,
txResult
)
=>
{
// TODO here should send the result to the dom-console
console
.
log
(
'function call'
,
error
,
txResult
)
alert
(
error
+
' '
+
txResult
.
transactionHash
)
})
}
else
{
alert
(
error
)
}
})
})
if
(
lookupOnly
&&
!
inputs
.
length
)
{
handleCallButtonClick
()
}
// TODO the auto call to constant function has been removed. needs to readd it later.
var
$contractProperty
=
$
(
'<div class="contractProperty"/>'
)
var
$contractProperty
=
$
(
`<div class="contractProperty
${
css
.
buttonsContainer
}
"></div>`
)
$contractProperty
.
append
(
button
)
.
append
((
lookupOnly
&&
!
inputs
.
length
)
?
$outputOverride
:
inputField
)
if
(
isConstructor
)
{
$contractProperty
.
addClass
(
'constructor'
)
}
if
(
lookupOnly
)
{
$contractProperty
.
addClass
(
'constant'
)
}
if
(
args
.
abi
.
inputs
&&
args
.
abi
.
inputs
.
length
>
0
)
{
if
(
args
.
funABI
.
inputs
&&
args
.
funABI
.
inputs
.
length
>
0
)
{
$contractProperty
.
addClass
(
'hasArgs'
)
}
if
(
args
.
abi
.
payable
===
true
)
{
if
(
args
.
funABI
.
payable
===
true
)
{
$contractProperty
.
addClass
(
'payable'
)
}
return
$contractProperty
.
append
(
outputSpan
)
}
UniversalDApp
.
prototype
.
linkBytecode
=
function
(
contractName
,
cb
)
{
var
self
=
this
var
bytecode
=
self
.
getContractByName
(
contractName
).
bytecode
if
(
bytecode
.
indexOf
(
'_'
)
<
0
)
{
return
cb
(
null
,
bytecode
)
}
var
m
=
bytecode
.
match
(
/__
([^
_
]{1,36})
__/
)
if
(
!
m
)
{
return
cb
(
'Invalid bytecode format.'
)
}
var
libraryName
=
m
[
1
]
if
(
!
self
.
getContractByName
(
libraryName
))
{
return
cb
(
'Library '
+
libraryName
+
' not found.'
)
}
self
.
deployLibrary
(
libraryName
,
function
(
err
,
address
)
{
if
(
err
)
{
return
cb
(
err
)
}
var
libLabel
=
'__'
+
libraryName
+
Array
(
39
-
libraryName
.
length
).
join
(
'_'
)
var
hexAddress
=
address
.
toString
(
'hex'
)
if
(
hexAddress
.
slice
(
0
,
2
)
===
'0x'
)
{
hexAddress
=
hexAddress
.
slice
(
2
)
}
hexAddress
=
Array
(
40
-
hexAddress
.
length
+
1
).
join
(
'0'
)
+
hexAddress
while
(
bytecode
.
indexOf
(
libLabel
)
>=
0
)
{
bytecode
=
bytecode
.
replace
(
libLabel
,
hexAddress
)
}
self
.
getContractByName
(
contractName
).
bytecode
=
bytecode
self
.
linkBytecode
(
contractName
,
cb
)
})
}
UniversalDApp
.
prototype
.
deployLibrary
=
function
(
contractName
,
cb
)
{
var
self
=
this
if
(
self
.
getContractByName
(
contractName
).
address
)
{
return
cb
(
null
,
self
.
getContractByName
(
contractName
).
address
)
}
var
bytecode
=
self
.
getContractByName
(
contractName
).
bytecode
if
(
bytecode
.
indexOf
(
'_'
)
>=
0
)
{
self
.
linkBytecode
(
contractName
,
function
(
err
,
bytecode
)
{
if
(
err
)
cb
(
err
)
else
self
.
deployLibrary
(
contractName
,
cb
)
})
}
else
{
self
.
runTx
({
data
:
bytecode
,
useCall
:
false
},
function
(
err
,
txResult
)
{
if
(
err
)
{
return
cb
(
err
)
}
var
address
=
self
.
executionContext
.
isVM
()
?
txResult
.
result
.
createdAddress
:
txResult
.
result
.
contractAddress
self
.
getContractByName
(
contractName
).
address
=
address
cb
(
err
,
address
)
})
}
}
UniversalDApp
.
prototype
.
clickContractAt
=
function
(
self
,
$output
,
contract
)
{
var
address
=
prompt
(
'What Address is this contract at in the Blockchain? ie: 0xdeadbeaf...'
)
self
.
getInstanceInterface
(
contract
,
address
,
$output
)
return
$contractProperty
}
UniversalDApp
.
prototype
.
runTx
=
function
(
args
,
cb
)
{
...
...
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