This commit is contained in:
Alexey 2020-10-21 17:42:50 +03:00
parent c20d518413
commit db5f1b42fa
14 changed files with 2011 additions and 26 deletions

26
abi/deployer.abi.json Normal file
View File

@ -0,0 +1,26 @@
[
{
"inputs": [
{
"internalType": "bytes",
"name": "_initCode",
"type": "bytes"
},
{
"internalType": "bytes32",
"name": "_salt",
"type": "bytes32"
}
],
"name": "deploy",
"outputs": [
{
"internalType": "address payable",
"name": "createdContract",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
]

95
abi/ens.mock.abi.json Normal file
View File

@ -0,0 +1,95 @@
[
{
"inputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"name": "registry",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"name": "resolver",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "_node",
"type": "bytes32"
}
],
"name": "addr",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "_node",
"type": "bytes32"
},
{
"internalType": "address",
"name": "_addr",
"type": "address"
}
],
"name": "setAddr",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32[]",
"name": "_nodes",
"type": "bytes32[]"
},
{
"internalType": "address[]",
"name": "_addresses",
"type": "address[]"
}
],
"name": "setAddrBulk",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]

View File

@ -12,7 +12,13 @@
<b-icon icon="check" /> <b-icon icon="check" />
<span>Completed</span> <span>Completed</span>
</div> </div>
<b-button v-else type="is-primary" outlined icon-left="tool"> <b-button
v-else
type="is-primary"
outlined
icon-left="tool"
@click="onDeploy"
>
Deploy Deploy
</b-button> </b-button>
</div> </div>
@ -20,6 +26,7 @@
</template> </template>
<script> <script>
import { mapActions } from 'vuex'
import Diamond from '@/components/Diamond' import Diamond from '@/components/Diamond'
export default { export default {
@ -32,5 +39,12 @@ export default {
required: true, required: true,
}, },
}, },
methods: {
...mapActions('deploy', ['deployContract']),
// todo pass ens domain here
onDeploy(/* domain */) {
this.deployContract({ domain: 'torn.deploy.tornadocash.eth' })
},
},
} }
</script> </script>

View File

@ -11,10 +11,17 @@
<script> <script>
import Navbar from '@/components/Navbar' import Navbar from '@/components/Navbar'
import { mapActions } from 'vuex'
export default { export default {
components: { components: {
Navbar, Navbar,
}, },
mounted() {
this.initProvider()
},
methods: {
...mapActions('provider', ['initProvider']),
},
} }
</script> </script>

42
networkConfig.js Normal file
View File

@ -0,0 +1,42 @@
const networkConfig = {
netId1: {
rpcCallRetryAttempt: 15,
gasPrices: { instant: 80, fast: 50, standard: 25, low: 8 },
currencyName: 'ETH',
explorerUrl: {
tx: 'https://etherscan.io/tx/',
address: 'https://etherscan.io/address/',
},
networkName: 'Mainnet',
rpcUrls: {
Infura: {
name: 'Infura',
url: 'https://mainnet.infura.io/v3/da564f81919d40c9a3bcaee4ff44438d',
},
MyCrypto: { name: 'MyCrypto', url: 'https://api.mycryptoapi.com/eth' },
},
deployerContract: '0xce0042b868300000d44a59004da54a005ffdcf9f',
pollInterval: 60,
},
netId42: {
rpcCallRetryAttempt: 15,
gasPrices: { instant: 80, fast: 50, standard: 25, low: 8 },
currencyName: 'kETH',
explorerUrl: {
tx: 'https://kovan.etherscan.io/tx/',
address: 'https://kovan.etherscan.io/address/',
},
networkName: 'Kovan',
deployerContract: '0xce0042b868300000d44a59004da54a005ffdcf9f',
rpcUrls: {
Infura: {
name: 'Infura',
url: 'https://kovan.infura.io/v3/9b8f0ddb3e684ece890f594bf1710c88',
},
'POA.network': { name: 'POA.network', url: 'https://kovan.poa.network' },
},
pollInterval: 200,
},
}
export default networkConfig

View File

@ -15,7 +15,8 @@
"node-sass": "^4.14.1", "node-sass": "^4.14.1",
"nuxt": "^2.14.6", "nuxt": "^2.14.6",
"nuxt-buefy": "^0.4.3", "nuxt-buefy": "^0.4.3",
"sass-loader": "^10.0.3" "sass-loader": "^10.0.3",
"web3": "1.2.6"
}, },
"devDependencies": { "devDependencies": {
"@nuxtjs/eslint-config": "^3.1.0", "@nuxtjs/eslint-config": "^3.1.0",

File diff suppressed because one or more lines are too long

68
store/deploy.js Normal file
View File

@ -0,0 +1,68 @@
/* eslint-disable no-console */
import Web3 from 'web3'
import { numberToHex } from 'web3-utils'
import deployerABI from '../abi/deployer.abi.json'
import deploymentActions from '../static/deploymentActions.json'
const state = () => {
return {}
}
const getters = {
deployerContract: (state, getters, rootState, rootGetters) => {
const { deployerContract, rpcUrls } = rootGetters['provider/getNetwork']
const web3 = new Web3(rpcUrls.Infura.url)
return new web3.eth.Contract(deployerABI, deployerContract)
},
}
const mutations = {}
const actions = {
async deployContract(
{ state, dispatch, getters, rootGetters, commit, rootState },
{ domain }
) {
try {
const ethAccount = rootGetters['provider/getAccount']
const { salt } = deploymentActions
const { bytecode } = deploymentActions.actions.filter((action) => {
return action.domain === domain
})[0]
const data = getters.deployerContract.methods
.deploy(bytecode, salt)
.encodeABI()
const gas = await getters.deployerContract.methods
.deploy(bytecode, salt)
.estimateGas({ from: ethAccount })
const callParams = {
method: 'eth_sendTransaction',
params: [
{
from: ethAccount,
to: getters.deployerContract.address,
gas: numberToHex(gas + 100000),
gasPrice: '0x100000000',
value: 0,
data,
},
],
from: ethAccount,
}
const txHash = await dispatch('provider/sendRequest', callParams, {
root: true,
})
console.log('txHash', txHash)
} catch (e) {
console.error('deployContract', e.message)
}
},
}
export default {
namespaced: true,
state,
getters,
mutations,
actions,
}

219
store/provider/actions.js Normal file
View File

@ -0,0 +1,219 @@
import Web3 from 'web3'
import { toChecksumAddress, hexToNumberString } from 'web3-utils'
import networkConfig from '@/networkConfig'
import {
SET_ACCOUNT,
SET_BALANCE,
SET_NETWORK,
SET_PROVIDER_API,
SET_NETWORK_NAME,
SET_PROVIDER_NAME,
} from './constant'
const repeatUntilResult = (action, totalAttempts, retryAttempt = 1) =>
new Promise((resolve, reject) => {
const iteration = async () => {
const result = await action()
if (!result) {
if (retryAttempt <= totalAttempts) {
retryAttempt++
setTimeout(iteration, 1000)
} else {
return reject(new Error('tx not minted'))
}
} else {
resolve(result)
}
}
iteration()
})
export default {
async initProvider({ commit, state, dispatch }, { name, network } = {}) {
try {
commit(SET_PROVIDER_NAME, name)
commit(SET_NETWORK_NAME, network)
await dispatch('_checkVersion')
await dispatch('_initProvider')
await dispatch('getBalance', state.account)
} catch (err) {
throw new Error(err.message)
}
},
async sendRequest({ commit, dispatch, getters, state }, params) {
const provider = getters.getProvider
try {
const request = (version, args) =>
version === 'old'
? dispatch('_sendAsync', args)
: provider.request(args)
const result = await request(state.provider.version, params)
return result
} catch (err) {
throw new Error(err.message)
}
},
async contractRequest(
{ dispatch, getters },
{ methodName, data, to, from, gas, value = 0 }
) {
const { rpcCallRetryAttempt, rpcUrl, blockGasLimit } = getters.getNetwork
try {
const web3 = new Web3(rpcUrl)
const params = {
data,
to,
from,
value,
gas: gas || blockGasLimit + 100000,
}
const transaction = await repeatUntilResult(
() => web3.eth[methodName](params),
rpcCallRetryAttempt
)
return transaction
} catch (err) {
throw new Error(err.message)
}
},
async checkNetworkVersion({ commit, dispatch }) {
try {
const id = await dispatch('sendRequest', { method: 'net_version' })
commit(SET_NETWORK, { ...networkConfig[`netId${id}`], id: Number(id) })
window.localStorage.setItem(
'network',
networkConfig[`netId${id}`].networkName
)
} catch (err) {
throw new Error(err.message)
}
},
async getBalance({ dispatch, commit, getters }, account) {
const { rpcCallRetryAttempt } = getters.getNetwork
try {
const params = {
method: 'eth_getBalance',
params: [account, 'latest'],
}
const balance = await repeatUntilResult(
() => dispatch('sendRequest', params),
rpcCallRetryAttempt
)
commit(SET_BALANCE, hexToNumberString(balance))
} catch (err) {
throw new Error(err.message)
}
},
async waitForTxReceipt({ dispatch, getters }, { txHash }) {
const { rpcCallRetryAttempt } = getters.getNetwork
try {
const params = {
method: 'eth_getTransactionReceipt',
params: [txHash],
}
const tx = await repeatUntilResult(
() => dispatch('sendRequest', params),
rpcCallRetryAttempt
)
return tx
} catch (err) {
throw new Error(err.message)
}
},
_sendAsync({ getters }, { method, params, from }) {
const provider = getters.getProvider
const { id } = getters.getNetwork
switch (id) {
case 77:
case 99:
case 100:
from = undefined
break
}
return new Promise((resolve, reject) => {
provider.sendAsync(
{
method,
params,
jsonrpc: '2.0',
from,
},
(err, response) => {
if (err) {
reject(err)
}
if (response.error) {
reject(response.error)
} else {
resolve(response.result)
}
}
)
})
},
async _initProvider({ commit, state, dispatch, getters }) {
const provider = getters.getProvider
try {
const request = (version) =>
version === 'old'
? provider.enable()
: dispatch('sendRequest', { method: 'eth_requestAccounts' })
const [account] = await request(state.provider.version)
if (!account) {
throw new Error('Locked metamask')
}
provider.on('accountsChanged', (accounts) =>
dispatch('_onAccountsChanged', accounts)
)
provider.on('chainChanged', (id) => dispatch('_onNetworkChanged', { id }))
commit(SET_ACCOUNT, toChecksumAddress(account))
await dispatch('checkNetworkVersion')
} catch (err) {
throw new Error(err.message)
}
},
_onNetworkChanged({ commit }, { id }) {
commit(SET_NETWORK, { ...networkConfig[`netId${id}`], id: Number(id) })
},
_onAccountsChanged({ newAccount, commit }, accounts) {
const [account] = accounts
commit(SET_ACCOUNT, toChecksumAddress(account))
window.location.reload()
},
_checkVersion({ getters, commit }) {
const provider = getters.getProvider
if (provider && provider.request) {
commit(SET_PROVIDER_API, 'new')
} else {
commit(SET_PROVIDER_API, 'old')
}
},
}

View File

@ -0,0 +1,13 @@
export const MAIN = 'provider'
export const SET_BALANCE = 'provider/SET_BALANCE'
export const SET_NETWORK = 'provider/SET_NETWORK'
export const SET_ACCOUNT = 'provider/SET_ACCOUNT'
export const SET_NETWORK_NAME = 'provider/SET_NETWORK_NAME'
export const SET_PROVIDER = 'provider/SET_PROVIDER'
export const SET_PROVIDER_API = 'provider/SET_PROVIDER_API'
export const SET_PROVIDER_NAME = 'provider/SET_PROVIDER_NAME'
export const SET_GAS_PRICE = 'provider/SET_GAS_PRICE'

25
store/provider/getters.js Normal file
View File

@ -0,0 +1,25 @@
import Web3 from 'web3'
import networkConfig from '@/networkConfig'
export default {
getProvider: (state, getters) => {
return window.ethereum
},
getProviderName: ({ provider }) => {
return provider.name
},
getWeb3: (state, getters) => {
const provider = getters.getProvider
return Object.freeze(new Web3(provider))
},
getBalance: (state) => {
return state.balance
},
getNetwork: (state) => {
const id = state.network.id
return { ...networkConfig[`netId${id}`], id: Number(id) }
},
getAccount: (state) => {
return state.account
},
}

View File

@ -0,0 +1,29 @@
import {
SET_ACCOUNT,
SET_NETWORK,
SET_BALANCE,
SET_PROVIDER_API,
SET_NETWORK_NAME,
SET_PROVIDER_NAME,
} from './constant'
export default {
[SET_BALANCE](state, balance) {
this._vm.$set(state, 'balance', balance)
},
[SET_PROVIDER_API](state, version) {
this._vm.$set(state.provider, 'version', version)
},
[SET_PROVIDER_NAME](state, name) {
this._vm.$set(state.provider, 'name', name)
},
[SET_ACCOUNT](state, account) {
this._vm.$set(state, 'account', account)
},
[SET_NETWORK](state, network) {
this._vm.$set(state, 'network', network)
},
[SET_NETWORK_NAME](state, name) {
this._vm.$set(state.network, 'name', name)
},
}

12
store/provider/state.js Normal file
View File

@ -0,0 +1,12 @@
export default () => ({
account: null,
network: {
name: 'mainnet',
id: 1,
},
provider: {
name: 'metamask',
version: 'new',
},
balance: 0,
})

1374
yarn.lock

File diff suppressed because it is too large Load Diff