juice-shop

Форк
0
/
web3-sandbox.component.ts 
307 строк · 9.0 Кб
1
import { Component, ChangeDetectorRef } from '@angular/core'
2
import { KeysService } from '../Services/keys.service'
3
import { SnackBarHelperService } from '../Services/snack-bar-helper.service'
4
import { getDefaultProvider, ethers } from 'ethers'
5
import {
6
  createClient,
7
  connect,
8
  disconnect,
9
  getAccount,
10
  InjectedConnector
11
} from '@wagmi/core'
12
import {
13
  solidityCompiler
14
} from 'solidity-browser-compiler'
15

16
// eslint-disable-next-line @typescript-eslint/no-unused-vars
17
const client = createClient({
18
  autoConnect: true,
19
  provider: getDefaultProvider()
20
})
21
const { ethereum } = window
22
const compilerReleases = {
23
  '0.8.21': 'soljson-v0.8.21+commit.d9974bed.js',
24
  '0.8.9': 'soljson-v0.8.9+commit.e5eed63a.js',
25
  '0.7.6': 'soljson-v0.7.6+commit.7338295f.js',
26
  '0.6.12': 'soljson-v0.6.12+commit.27d51765.js',
27
  '0.5.17': 'soljson-v0.5.17+commit.d19bba13.js',
28
  '0.4.26': 'soljson-v0.4.26+commit.4563c3fc.js',
29
  '0.3.6': 'soljson-v0.3.6+commit.3fc68da5.js',
30
  '0.2.2': 'soljson-v0.2.2+commit.ef92f566.js',
31
  '0.1.7': 'soljson-v0.1.7+commit.b4e666cc.js'
32
}
33
@Component({
34
  selector: 'app-web3-sandbox',
35
  templateUrl: './web3-sandbox.component.html',
36
  styleUrls: ['./web3-sandbox.component.scss']
37
})
38
export class Web3SandboxComponent {
39
  constructor (
40
    private readonly keysService: KeysService,
41
    private readonly snackBarHelperService: SnackBarHelperService,
42
    private readonly changeDetectorRef: ChangeDetectorRef
43
  ) {}
44

45
  ngOnInit (): void {
46
    this.handleAuth()
47
    window.ethereum.on('chainChanged', this.handleChainChanged.bind(this))
48
  }
49

50
  userData: object
51
  session = false
52
  metamaskAddress = ''
53
  selectedContractName: string
54
  compiledContracts = []
55
  deployedContractAddress = ''
56
  contractNames = []
57
  commonGweiValue: number = 0
58
  contractFunctions = []
59
  invokeOutput = ''
60
  selectedCompilerVersion: string = '0.8.21'
61
  compilerVersions: string[] = Object.keys(compilerReleases)
62
  compilerErrors = []
63

64
  code: string = `// SPDX-License-Identifier: MIT
65
pragma solidity ^0.8.14;
66

67
contract HelloWorld {
68
    function get()public pure returns (string memory){
69
        return 'Hello Contracts';
70
    }
71
}`
72
  editorOptions = {
73
    mode: 'text/x-solidity',
74
    theme: 'dracula',
75
    lineNumbers: true,
76
    lineWrapping: true
77
  }
78

79
  async compileAndFetchContracts (code: string) {
80
    try {
81
      this.deployedContractAddress = ''
82
      const selectedVersion = compilerReleases[
83
        this.selectedCompilerVersion
84
      ] as string
85

86
      if (!selectedVersion) {
87
        console.error('Selected compiler version not found.')
88
        return
89
      }
90

91
      const compilerInput = {
92
        version: `https://binaries.soliditylang.org/bin/${selectedVersion}`,
93
        contractBody: code
94
      }
95
      const output = await solidityCompiler(compilerInput)
96
      if (output.errors && output.errors.length > 0 && !output.contracts) {
97
        this.compiledContracts = null
98
        console.log(output.errors)
99
        this.compilerErrors.push(...output.errors)
100
      } else {
101
        this.compilerErrors = []
102
        console.log('output', output)
103
        this.compiledContracts = output.contracts.Compiled_Contracts
104
        this.contractNames = Object.keys(this.compiledContracts)
105
        this.selectedContractName = this.contractNames[0]
106
      }
107
    } catch (error) {
108
      console.error('Error compiling contracts:', error)
109
    }
110
  }
111

112
  async deploySelectedContract () {
113
    if (!this.session) {
114
      this.snackBarHelperService.open('PLEASE_CONNECT_WEB3_WALLET', 'errorBar')
115
      return
116
    }
117
    try {
118
      const selectedContractName = this.selectedContractName
119
      const selectedContract = this.compiledContracts[selectedContractName]
120

121
      if (!selectedContract) {
122
        console.error('Selected contract not found.')
123
        return
124
      }
125

126
      const provider = new ethers.providers.Web3Provider(window.ethereum)
127
      const signer = provider.getSigner()
128

129
      const contractBytecode = selectedContract.evm.bytecode.object
130
      const contractAbi = selectedContract.abi
131

132
      const factory = new ethers.ContractFactory(
133
        contractAbi,
134
        contractBytecode,
135
        signer
136
      )
137
      const transactionOptions: ethers.PayableOverrides = {}
138
      if (this.commonGweiValue > 0) {
139
        transactionOptions.value = ethers.utils.parseUnits(
140
          this.commonGweiValue.toString(),
141
          'gwei'
142
        )
143
      }
144
      const contract = await factory.deploy(transactionOptions)
145
      await contract.deployed()
146
      this.deployedContractAddress = contract.address
147

148
      this.contractFunctions = contractAbi
149
        .filter((item) => item.type === 'function')
150
        .map((func) => {
151
          const inputHints =
152
            func.inputs.length > 0
153
              ? this.getInputHints(func.inputs)
154
              : 'No inputs'
155
          return {
156
            ...func,
157
            inputValues: '',
158
            outputValue: '',
159
            inputHints
160
          }
161
        })
162

163
      console.log(this.contractFunctions)
164
    } catch (error) {
165
      console.error('Error deploying contract:', error)
166
    }
167
  }
168

169
  getInputHints (inputs: Array<{ name: string, type: string }>): string {
170
    return inputs.map((input) => `${input.name}: ${input.type}`).join(', ')
171
  }
172

173
  parseInputValue (value: string, type: string) {
174
    if (type === 'bool') {
175
      return value.toLowerCase() === 'true'
176
    } else {
177
      return value
178
    }
179
  }
180

181
  async invokeFunction (func) {
182
    if (!this.session) {
183
      this.snackBarHelperService.open('PLEASE_CONNECT_WEB3_WALLET', 'errorBar')
184
      return
185
    }
186
    try {
187
      const selectedContract =
188
        this.compiledContracts[this.selectedContractName]
189

190
      const provider = new ethers.providers.Web3Provider(window.ethereum)
191
      const signer = provider.getSigner()
192
      const contract = new ethers.Contract(
193
        this.deployedContractAddress,
194
        selectedContract.abi,
195
        signer
196
      )
197

198
      const inputs =
199
        func.inputValues.trim() !== ''
200
          ? func.inputValues.split(',').map((value, index) => {
201
            const inputType = func.inputs[index].type
202
            return this.parseInputValue(value.trim(), inputType)
203
          })
204
          : []
205
      const transactionOptions: ethers.PayableOverrides = {}
206
      if (this.commonGweiValue > 0) {
207
        transactionOptions.value = ethers.utils.parseUnits(
208
          this.commonGweiValue.toString(),
209
          'gwei'
210
        )
211
      }
212
      const transaction = await contract.functions[func.name](
213
        ...inputs,
214
        transactionOptions
215
      )
216
      console.log(transaction)
217

218
      if (
219
        func.outputs.length > 0 &&
220
        (func.stateMutability === 'view' || func.stateMutability === 'pure')
221
      ) {
222
        console.log('hello')
223
        const outputValue = transaction[0].toString()
224
        const updatedFunc = this.contractFunctions.find(
225
          (f) => f.name === func.name
226
        )
227
        if (updatedFunc) {
228
          updatedFunc.outputValue = outputValue
229
          const index = this.contractFunctions.indexOf(func)
230
          if (index !== -1) {
231
            this.contractFunctions[index] = updatedFunc
232
          }
233
        }
234
        console.log(func.outputValue)
235
      }
236
      console.log('Invoked:', transaction)
237
    } catch (error) {
238
      console.error('Error invoking function', error)
239
      const updatedFunc = this.contractFunctions.find(
240
        (f) => f.name === func.name
241
      )
242
      if (updatedFunc) {
243
        updatedFunc.outputValue = error.message
244
        const index = this.contractFunctions.indexOf(func)
245
        if (index !== -1) {
246
          this.contractFunctions[index] = updatedFunc
247
        }
248
      }
249
    }
250
  }
251

252
  async handleChainChanged (chainId: string) {
253
    await this.handleAuth()
254
  }
255

256
  async handleAuth () {
257
    try {
258
      const { isConnected } = getAccount()
259

260
      if (isConnected) {
261
        await disconnect()
262
      }
263
      if (!window.ethereum) {
264
        this.snackBarHelperService.open('PLEASE_INSTALL_WEB3_WALLET', 'errorBar')
265
        return
266
      }
267

268
      const provider = await connect({ connector: new InjectedConnector() })
269
      this.metamaskAddress = provider.account
270
      this.userData = {
271
        address: provider.account,
272
        chain: provider.chain.id,
273
        network: 'evm'
274
      }
275
      await ethereum.request({
276
        method: 'wallet_addEthereumChain',
277
        params: [
278
          {
279
            chainId: '0xaa36a7',
280
            chainName: 'Sepolia Test Network',
281
            nativeCurrency: {
282
              name: 'SepoliaETH',
283
              symbol: 'ETH',
284
              decimals: 18
285
            },
286
            rpcUrls: ['https://ethereum-sepolia.blockpi.network/v1/rpc/public'],
287
            blockExplorerUrls: ['https://sepolia.etherscan.io/']
288
          }
289
        ]
290
      })
291
      const targetChainId = '11155111'
292
      const currentChainId = String(provider.chain?.id)
293

294
      if (provider && currentChainId !== targetChainId) {
295
        this.session = false
296
        this.snackBarHelperService.open('PLEASE_CONNECT_TO_SEPOLIA_NETWORK', 'errorBar')
297
      } else {
298
        console.log('Should show ethereum chain now')
299
        this.session = true
300
      }
301
      console.log('session', this.session)
302
      this.changeDetectorRef.detectChanges()
303
    } catch (err) {
304
      console.log('An error occured')
305
    }
306
  }
307
}
308

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.