diff --git a/package-lock.json b/package-lock.json index f091d06..4faac1f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4484,9 +4484,9 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "caver-js": { - "version": "0.0.2-r", - "resolved": "https://registry.npmjs.org/caver-js/-/caver-js-0.0.2-r.tgz", - "integrity": "sha512-KycgwzclL4SNyxudfHZTdoyuPMsK4ShdGCYEusY1bGJV7B4NyN9SeE57w5eQbig3WePTNBb89CFDBixvC0YYcQ==", + "version": "0.0.2-u", + "resolved": "https://registry.npmjs.org/caver-js/-/caver-js-0.0.2-u.tgz", + "integrity": "sha512-zmWhGE2NGwalksrelIJVU/ztl5pTQlVcCAsYCZKE4hAGeALt/3wIG0wCTh/QDkLY7TGBzB/zABqm9DKgcO0P2g==", "requires": { "@babel/polyfill": "7.2.5", "@babel/runtime": "7.3.1", diff --git a/package.json b/package.json index 4dd170d..606d26e 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "dependencies": { "bignumber.js": "^8.0.2", "bs58": "^4.0.1", - "caver-js": "0.0.2-r", + "caver-js": "0.0.2-u", "classnames": "^2.2.5", "dotenv": "^6.0.0", "dotenv-webpack": "^1.5.7", diff --git a/src/components/FeeDelegate.js b/src/components/FeeDelegate.js new file mode 100644 index 0000000..23e1c3f --- /dev/null +++ b/src/components/FeeDelegate.js @@ -0,0 +1,203 @@ +import React, { Component } from 'react' +import { Subject, fromEvent, of } from 'rxjs' +import { map, tap, take, takeUntil, catchError } from 'rxjs/operators' +import { ajax } from 'rxjs/ajax' + +import KlayRawTransactionDecoder from 'components/KlayRawTransactionDecoder' +import { feeDelegateLambdaURL } from 'constants/url' +import { caver } from 'utils/caver' + +import './FeeDelegate.scss' + +type Props = { + +} + +const generateRandomFeeDelegatedRawTx = (feedAddress, toAddress) => { + const rawTxcandidate = [randomTxType1, randomTxType2, randomTxType3, randomTxType4] + const idx = parseInt((Math.random() * 1000) % rawTxcandidate.length) + + return rawTxcandidate[idx](feedAddress, toAddress) +} + +const randomTxType1 = (feedAddress, toAddress) => ({ + type: 'FEE_DELEGATED_SMART_CONTRACT_DEPLOY', + from: feedAddress, + to: toAddress, + data: `0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029`, + gas: '3000000', +}) + +const randomTxType2 = (feedAddress, toAddress) => ({ + type: 'FEE_DELEGATED_VALUE_TRANSFER', + from: feedAddress, + to: toAddress, + value: 10, + gas: '3000000', +}) + +const randomTxType3 = (feedAddress, toAddress) => ({ + type: 'FEE_DELEGATED_VALUE_TRANSFER_MEMO', + from: feedAddress, + to: toAddress, + value: 20, + data: '0xdeadbeef', + gas: '3000000', +}) + +const randomTxType4 = (feedAddress, toAddress) => ({ + type: 'FEE_DELEGATED_SMART_CONTRACT_DEPLOY_WITH_RATIO', + from: feedAddress, + to: toAddress, + feeRatio: 10, + data: `0x608060405234801561001057600080fd5b506101de806100206000396000f3006080604052600436106100615763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416631a39d8ef81146100805780636353586b146100a757806370a08231146100ca578063fd6b7ef8146100f8575b3360009081526001602052604081208054349081019091558154019055005b34801561008c57600080fd5b5061009561010d565b60408051918252519081900360200190f35b6100c873ffffffffffffffffffffffffffffffffffffffff60043516610113565b005b3480156100d657600080fd5b5061009573ffffffffffffffffffffffffffffffffffffffff60043516610147565b34801561010457600080fd5b506100c8610159565b60005481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604081208054349081019091558154019055565b60016020526000908152604090205481565b336000908152600160205260408120805490829055908111156101af57604051339082156108fc029083906000818181858888f193505050501561019c576101af565b3360009081526001602052604090208190555b505600a165627a7a72305820627ca46bb09478a015762806cc00c431230501118c7c26c30ac58c4e09e51c4f0029`, + gas: '3000000', +}) + +class FeeDelegate extends Component { + destroy$ = new Subject() + + state = { + rawTx: '', + receipt: null, + isLoading: false, + isGenerating: false, + errorMessage: '', + } + + componentDidMount() { + fromEvent(this.decoderComp.$rawTransactionHex, 'input').pipe( + tap((e) => { + this.setState({ + rawTx: e.target.value, + hasError: false, + errorMessage: '', + }) + }), + takeUntil(this.destroy$), + ).subscribe() + } + + requestFeeDelegate = () => { + const { rawTx } = this.state + if (!rawTx) return + + this.setState({ + isLoading: true, + receipt: null, + }) + + try { + ajax.getJSON(feeDelegateLambdaURL + '/' + rawTx).pipe( + map((receipt) => { + console.log(receipt, 'receipt') + this.setState({ + receipt: receipt, + isLoading: false, + hasError: false, + errorMessage: '', + }) + }), + catchError((err) => { + console.log(err, 'err') + this.setState({ + receipt: null, + isLoading: false, + hasError: true, + errorMessage: err && JSON.stringify(err.response), + }) + + return of('no more request') + }), + take(1), + ).subscribe() + } catch (e) { + console.log(e, 'e') + this.setState({ + receipt: null, + isLoading: false, + hasError: true, + }) + } + } + + genRandomFeeDelegateRawTx = async () => { + this.setState({ + receipt: null, + hasError: false, + errorMessage: '', + isGenerating: true, + }) + const { address: feedAddress, privateKey } = caver.klay.accounts.create() + const { address: toAddress } = caver.klay.accounts.create() + + await fetch(`https://baobab.klaytnwallet.com/api/faucet/?address=${feedAddress}`) + + const senderTransaction = generateRandomFeeDelegatedRawTx(feedAddress, toAddress) + + const { rawTransaction } = await caver.klay.accounts.signTransaction(senderTransaction, privateKey) + + this.decoderComp.$rawTransactionHex.value = rawTransaction + this.decoderComp.$rawTransactionHex.dispatchEvent(new Event('input')) + + setTimeout(() => { + this.setState({ + isGenerating: false, + }) + }, 0) + } + + render() { + const { errorMessage, rawTx, receipt, hasError, isGenerating, isLoading } = this.state + + return ( +
+

Note: "FEE DELEGATE" tool only works when Klaytn baobab network is online.

+ + + {(isGenerating || isLoading) && ( + + )} + {hasError &&
Error occurred. {errorMessage}
} + {!hasError && receipt && ( +
+

Receipt:

+ {Object.entries(receipt).map(([fieldName, fieldValue]) => { + return ( +
+ {fieldName}: {fieldValue} {fieldName === 'txHash' && ( + + Check Detail + + )} +
+ ) + })} +
+ )} + this.decoderComp = comp} /> +
+ ) + } +} + +export default FeeDelegate \ No newline at end of file diff --git a/src/components/FeeDelegate.scss b/src/components/FeeDelegate.scss new file mode 100644 index 0000000..655788d --- /dev/null +++ b/src/components/FeeDelegate.scss @@ -0,0 +1,45 @@ +.FeeDelegate { + padding-bottom: 100px; +} + +.FeeDelegate__receipt { + font-size: 12px; + word-break: break-all; + border: 2px solid #eeeeee; + border-radius: 3px; + padding: 8px; + margin-bottom: 4px; +} + +.FeeDelegate__error { + color: red; + font-size: 14px; + margin-bottom: 4px; +} + +.FeeDelegate__receiptHeader { + font-size: 14px; + margin-bottom: 2px; +} + +.FeeDelegate__loading { + display: inline-block; + vertical-align: middle; + width: 20px; + height: 20px; +} + +.FeeDelegate__genButton, .FeeDelegate__requestButton { + display: inline-block; + vertical-align: middle; + margin-left: 4px; +} + +.FeeDelegate__notice { + margin-bottom: 4px; +} + +.FeeDelegate__scopeLink { + color: #6A8DDA; + text-decoration: underline; +} \ No newline at end of file diff --git a/src/components/KlayRawTransactionDecoder.js b/src/components/KlayRawTransactionDecoder.js index 7e70e3a..9b80d2a 100644 --- a/src/components/KlayRawTransactionDecoder.js +++ b/src/components/KlayRawTransactionDecoder.js @@ -92,11 +92,12 @@ class KlayRawTransactionDecoder extends Component { render() { const { result } = this.state + const { title } = this.props return (
- +