Interact with the smart contract details
All right! So you've deployed you smart contract through the SCUI! Lets show the end-user the contract details and if possible, interact with the contract as well.
So, if you clicked on the finish button after the last deployment step, you would have been redirected to this screen:

The contract/:contractAddress/show/:contractType
page.
This page displays the contract details that were setup in the contract/:contractType/create
page. Easy, right?
Let's have a look at what this component looks like.
Create the fixed-supply component inside the contract-show module
ng generate component contract-show/fixed-supply --project=simple-ico
The component must be generated by the angular cli and you should be ready to get your contract details.
Display the fixed-supply component with the matching :contractType param
...
import { FixedSupplyDeployment } from '@factory/fixed-supply.deployment';
@Component({
selector: 'app-container',
templateUrl: './container.component.html',
styleUrls: ['./container.component.css']
})
export class ContainerComponent implements OnInit {
contractAddress: string
contractType: string
FixedSupplyDeployment: string = FixedSupplyDeployment._type
<app-header></app-header>
<app-mobile-menu></app-mobile-menu>
<main id="crowdsale-show">
<app-fixed-supply *ngIf="FixedSupplyDeployment == contractType"></app-fixed-supply>
</main>
Get the fixed-supply contract details
By now, you should be familiar with the frontend framework, so here's the whole component code.
Basically, what is happening here is:
Init the component with
ngOnInit()
Get the
contractAddress
from the route paramsInitialize a new
SimpleCrowdsaleContract
instance passing the Wallet instanceConnect to the contract ABI and set the
contractAddress
from the routeThis is equivalent to passing the address to the new
web3.eth.Contract
call or calling newContract().at()
in other libraries
Subscribe to the crowdsale contract events. These events are the transactions happening for this contract in the Ethereum network. Web3 listens to these events using websockets
Instantiate a new
SimpleTokenContract
passing theWallet
instance and connect to its ABIGet the crowdsale data. Note that we are delegating these methods to the
SimpleCrowdsaleContract
class. This is a good design practiceGet the token data. Because the crowdsale contract has the token address stored in it, we can get it by calling the
this.crowdsale.instance.methods.token.call()
method. Await for it to return the value and set the address to the token contract instance
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { EthereumService } from '@service/ethereum.service';
import { WalletService } from '@service/wallet.service';
import { SharedService } from '@service/shared.service';
import { SimpleCrowdsaleContract } from '@contract/simplecrowdsale.contract';
import { SimpleTokenContract } from '@contract/simpletoken.contract';
declare var require: any
const ethers = require('ethers')
@Component({
selector: 'app-fixed-supply',
templateUrl: './fixed-supply.component.html',
styleUrls: ['./fixed-supply.component.css']
})
export class FixedSupplyComponent implements OnInit {
contractAddress: string
contractType: string
ethRaised: string = '0.0'
crowdsale: SimpleCrowdsaleContract
token: SimpleTokenContract
txHistory: Array<any> = []
txs: Array<string> = []
constructor(
public route: ActivatedRoute,
public eth: EthereumService,
public shared: SharedService,
public wallet: WalletService) {}
ngOnInit() {
this.route.params.subscribe(({ contractAddress, contractType }) => {
this.contractAddress = contractAddress
this.contractType = contractType
this.crowdsale = new SimpleCrowdsaleContract(this.wallet.getInstance())
this.crowdsale.connect()
this.crowdsale.setAddress(this.contractAddress)
this.subscribe()
this.token = new SimpleTokenContract(this.wallet.getInstance())
this.token.connect()
this.getCrowdsaleData()
this.getTokenData()
})
}
refresh(){
this.crowdsale.getEthRaised()
this.crowdsale.getAvailableTokens(this.token)
}
subscribe(){
this.crowdsale.subscribeToEvents()
.on('data', event => {
this.crowdsale.getEthRaised()
this.crowdsale.getAvailableTokens(this.token)
this.getTransaction(event.transactionHash)
}).on('error', error => {
console.log(error)
})
}
async getTransaction(hash: string){
if (this.txs.indexOf(hash) != -1) {
return false
}
this.txs.push(hash)
try {
let tx = await this.crowdsale.web3.eth.getTransaction(hash)
this.txHistory.unshift({
hash: tx.hash,
from: tx.from,
to: tx.to,
value: `ETH ${ethers.utils.formatEther(tx.value)}`
})
} catch (error) {
console.log(error)
}
}
async getCrowdsaleData(){
this.crowdsale.getEthRaised()
this.crowdsale.getBeneficiary()
this.crowdsale.getPrice()
this.crowdsale.web3.eth.getPastLogs({
fromBlock: '0x0',
address: this.crowdsale.address
}).then(res => {
res.forEach(rec => {
this.getTransaction(rec.transactionHash)
})
}).catch(err => console.log)
}
async getTokenData(){
let tokenAddress = await this.crowdsale.instance.methods.token().call()
this.token.setAddress(tokenAddress)
this.crowdsale.getAvailableTokens(this.token)
this.token.getName()
this.token.getSymbol()
}
}
Whenever a transaction happens for this crowdsale smart contract in the Ethereum address, the subscription will populate the txHistory
array and display it in the SCUI in real-time.
This is how the SCUI html looks like. Note that we are binding to the crowdsale and token instances. This is a good design practice. Also the template will show the data whenever it is ready or it changes:
<app-qr-code-modal [model]="crowdsale"></app-qr-code-modal>
<div class="container">
<h1 class="token-name">{{ token.name }} ({{ token.symbol }})</h1>
<div class="eth-raised">
<span class="balance text-truncate" style="max-width: 210px">{{ crowdsale.address }}</span>
<small>Crowdsale address</small>
<span class="go-icon" (click)="shared.displayCrowdsaleShowModal()"><i class="icon-copy"></i></span>
</div>
<div class="eth-raised">
<span class="balance"><strong>ETH</strong> {{ crowdsale.ethRaised }}</span>
<small>Amount raised</small>
<!-- <span class="go-icon" (click)="refresh()"><i class="icon-sync"></i></span> -->
</div>
<div class="eth-raised">
<span class="balance"><strong>ETH</strong> {{ crowdsale.price }}</span>
<small>Price</small>
</div>
<div class="eth-raised">
<span class="balance"><strong>{{ token.symbol }}</strong> {{ crowdsale.tokens }}</span>
<small>Available</small>
</div>
</div>
<section id="info" class="section">
<div class="container">
<h5 class="title">Contract information</h5>
<article class="info">
<small>Crowdsale beneficiary</small>
<a href="{{ eth.etherscanURL }}/address/{{ crowdsale.beneficiary }}" target="_blank" class="text-truncate">{{ crowdsale.beneficiary }}</a>
</article>
<article class="info">
<small>Crowdsale contract</small>
<a href="{{ eth.etherscanURL }}/address/{{ crowdsale.getAddress() }}" target="_blank" class="text-truncate">{{ crowdsale.getAddress() }}</a>
</article>
<article class="info">
<small>ERC20 Token contract</small>
<a href="{{ eth.etherscanURL }}/token/{{ token.getAddress() }}" target="_blank" class="text-truncate">{{ token.getAddress() }}</a>
</article>
</div>
</section>
<section id="tx-history" class="section">
<div class="container">
<h5 class="title">Transaction History</h5>
<article class="tx row" *ngFor="let tx of txHistory">
<div class="col-sm-3 hash">
<small>Hash</small>
<a href="{{ eth.etherscanURL }}/tx/{{ tx.hash }}" target="_blank" class="text-truncate">{{ tx.hash }}</a>
</div>
<div class="col-sm-3 from">
<small>From</small>
<a href="{{ eth.etherscanURL }}/address/{{ tx.from }}" target="_blank" class="text-truncate">{{ tx.from }}</a>
</div>
<div class="col-sm-3 to">
<small>To</small>
<a href="{{ eth.etherscanURL }}/address/{{ tx.to }}" target="_blank" class="text-truncate">{{ tx.to }}</a>
</div>
<div class="col-sm-3 value">
<small>Value</small>
<span class="text-truncate">{{ tx.value }}</span>
</div>
</article>
</div>
</section>
Last updated