mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-10-22 19:26:13 +02:00
Merge pull request #4814 from whymarrh/send-data
Add hex data input to send screen
This commit is contained in:
commit
76ac6bbb30
@ -164,6 +164,7 @@ var actions = {
|
|||||||
UPDATE_GAS_PRICE: 'UPDATE_GAS_PRICE',
|
UPDATE_GAS_PRICE: 'UPDATE_GAS_PRICE',
|
||||||
UPDATE_GAS_TOTAL: 'UPDATE_GAS_TOTAL',
|
UPDATE_GAS_TOTAL: 'UPDATE_GAS_TOTAL',
|
||||||
UPDATE_SEND_FROM: 'UPDATE_SEND_FROM',
|
UPDATE_SEND_FROM: 'UPDATE_SEND_FROM',
|
||||||
|
UPDATE_SEND_HEX_DATA: 'UPDATE_SEND_HEX_DATA',
|
||||||
UPDATE_SEND_TOKEN_BALANCE: 'UPDATE_SEND_TOKEN_BALANCE',
|
UPDATE_SEND_TOKEN_BALANCE: 'UPDATE_SEND_TOKEN_BALANCE',
|
||||||
UPDATE_SEND_TO: 'UPDATE_SEND_TO',
|
UPDATE_SEND_TO: 'UPDATE_SEND_TO',
|
||||||
UPDATE_SEND_AMOUNT: 'UPDATE_SEND_AMOUNT',
|
UPDATE_SEND_AMOUNT: 'UPDATE_SEND_AMOUNT',
|
||||||
@ -183,6 +184,7 @@ var actions = {
|
|||||||
setSendTokenBalance,
|
setSendTokenBalance,
|
||||||
updateSendTokenBalance,
|
updateSendTokenBalance,
|
||||||
updateSendFrom,
|
updateSendFrom,
|
||||||
|
updateSendHexData,
|
||||||
updateSendTo,
|
updateSendTo,
|
||||||
updateSendAmount,
|
updateSendAmount,
|
||||||
updateSendMemo,
|
updateSendMemo,
|
||||||
@ -838,6 +840,13 @@ function updateSendFrom (from) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateSendHexData (value) {
|
||||||
|
return {
|
||||||
|
type: actions.UPDATE_SEND_HEX_DATA,
|
||||||
|
value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateSendTo (to, nickname = '') {
|
function updateSendTo (to, nickname = '') {
|
||||||
return {
|
return {
|
||||||
type: actions.UPDATE_SEND_TO,
|
type: actions.UPDATE_SEND_TO,
|
||||||
|
@ -4,6 +4,7 @@ import PageContainerContent from '../../page-container/page-container-content.co
|
|||||||
import SendAmountRow from './send-amount-row/'
|
import SendAmountRow from './send-amount-row/'
|
||||||
import SendFromRow from './send-from-row/'
|
import SendFromRow from './send-from-row/'
|
||||||
import SendGasRow from './send-gas-row/'
|
import SendGasRow from './send-gas-row/'
|
||||||
|
import SendHexDataRow from './send-hex-data-row'
|
||||||
import SendToRow from './send-to-row/'
|
import SendToRow from './send-to-row/'
|
||||||
|
|
||||||
export default class SendContent extends Component {
|
export default class SendContent extends Component {
|
||||||
@ -20,6 +21,7 @@ export default class SendContent extends Component {
|
|||||||
<SendToRow updateGas={(updateData) => this.props.updateGas(updateData)} />
|
<SendToRow updateGas={(updateData) => this.props.updateGas(updateData)} />
|
||||||
<SendAmountRow updateGas={(updateData) => this.props.updateGas(updateData)} />
|
<SendAmountRow updateGas={(updateData) => this.props.updateGas(updateData)} />
|
||||||
<SendGasRow />
|
<SendGasRow />
|
||||||
|
<SendHexDataRow />
|
||||||
</div>
|
</div>
|
||||||
</PageContainerContent>
|
</PageContainerContent>
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
export { default } from './send-hex-data-row.container'
|
@ -0,0 +1,40 @@
|
|||||||
|
import React, { Component } from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import SendRowWrapper from '../send-row-wrapper'
|
||||||
|
|
||||||
|
export default class SendHexDataRow extends Component {
|
||||||
|
static propTypes = {
|
||||||
|
data: PropTypes.string,
|
||||||
|
inError: PropTypes.bool,
|
||||||
|
updateSendHexData: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
static contextTypes = {
|
||||||
|
t: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
onInput = (event) => {
|
||||||
|
const {updateSendHexData} = this.props
|
||||||
|
event.target.value = event.target.value.replace(/\n/g, '')
|
||||||
|
updateSendHexData(event.target.value || null)
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const {inError} = this.props
|
||||||
|
const {t} = this.context
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SendRowWrapper
|
||||||
|
label={`${t('hexData')}:`}
|
||||||
|
showError={inError}
|
||||||
|
errorType={'amount'}
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
onInput={this.onInput}
|
||||||
|
placeholder="Optional"
|
||||||
|
className="send-v2__hex-data__input"
|
||||||
|
/>
|
||||||
|
</SendRowWrapper>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
import { connect } from 'react-redux'
|
||||||
|
import {
|
||||||
|
updateSendHexData,
|
||||||
|
} from '../../../../actions'
|
||||||
|
import SendHexDataRow from './send-hex-data-row.component'
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(SendHexDataRow)
|
||||||
|
|
||||||
|
function mapStateToProps (state) {
|
||||||
|
return {
|
||||||
|
data: state.metamask.send.data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapDispatchToProps (dispatch) {
|
||||||
|
return {
|
||||||
|
updateSendHexData (data) {
|
||||||
|
return dispatch(updateSendHexData(data))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ export default class SendFooter extends Component {
|
|||||||
static propTypes = {
|
static propTypes = {
|
||||||
addToAddressBookIfNew: PropTypes.func,
|
addToAddressBookIfNew: PropTypes.func,
|
||||||
amount: PropTypes.string,
|
amount: PropTypes.string,
|
||||||
|
data: PropTypes.string,
|
||||||
clearSend: PropTypes.func,
|
clearSend: PropTypes.func,
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
editingTransactionId: PropTypes.string,
|
editingTransactionId: PropTypes.string,
|
||||||
@ -41,6 +42,7 @@ export default class SendFooter extends Component {
|
|||||||
const {
|
const {
|
||||||
addToAddressBookIfNew,
|
addToAddressBookIfNew,
|
||||||
amount,
|
amount,
|
||||||
|
data,
|
||||||
editingTransactionId,
|
editingTransactionId,
|
||||||
from: {address: from},
|
from: {address: from},
|
||||||
gasLimit: gas,
|
gasLimit: gas,
|
||||||
@ -68,6 +70,7 @@ export default class SendFooter extends Component {
|
|||||||
const promise = editingTransactionId
|
const promise = editingTransactionId
|
||||||
? update({
|
? update({
|
||||||
amount,
|
amount,
|
||||||
|
data,
|
||||||
editingTransactionId,
|
editingTransactionId,
|
||||||
from,
|
from,
|
||||||
gas,
|
gas,
|
||||||
@ -76,7 +79,7 @@ export default class SendFooter extends Component {
|
|||||||
to,
|
to,
|
||||||
unapprovedTxs,
|
unapprovedTxs,
|
||||||
})
|
})
|
||||||
: sign({ selectedToken, to, amount, from, gas, gasPrice })
|
: sign({ data, selectedToken, to, amount, from, gas, gasPrice })
|
||||||
|
|
||||||
Promise.resolve(promise)
|
Promise.resolve(promise)
|
||||||
.then(() => history.push(CONFIRM_TRANSACTION_ROUTE))
|
.then(() => history.push(CONFIRM_TRANSACTION_ROUTE))
|
||||||
|
@ -18,6 +18,7 @@ import {
|
|||||||
getSendFromObject,
|
getSendFromObject,
|
||||||
getSendTo,
|
getSendTo,
|
||||||
getSendToAccounts,
|
getSendToAccounts,
|
||||||
|
getSendHexData,
|
||||||
getTokenBalance,
|
getTokenBalance,
|
||||||
getUnapprovedTxs,
|
getUnapprovedTxs,
|
||||||
} from '../send.selectors'
|
} from '../send.selectors'
|
||||||
@ -35,6 +36,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(SendFooter)
|
|||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
return {
|
return {
|
||||||
amount: getSendAmount(state),
|
amount: getSendAmount(state),
|
||||||
|
data: getSendHexData(state),
|
||||||
editingTransactionId: getSendEditingTransactionId(state),
|
editingTransactionId: getSendEditingTransactionId(state),
|
||||||
from: getSendFromObject(state),
|
from: getSendFromObject(state),
|
||||||
gasLimit: getGasLimit(state),
|
gasLimit: getGasLimit(state),
|
||||||
@ -52,9 +54,10 @@ function mapStateToProps (state) {
|
|||||||
function mapDispatchToProps (dispatch) {
|
function mapDispatchToProps (dispatch) {
|
||||||
return {
|
return {
|
||||||
clearSend: () => dispatch(clearSend()),
|
clearSend: () => dispatch(clearSend()),
|
||||||
sign: ({ selectedToken, to, amount, from, gas, gasPrice }) => {
|
sign: ({ selectedToken, to, amount, from, gas, gasPrice, data }) => {
|
||||||
const txParams = constructTxParams({
|
const txParams = constructTxParams({
|
||||||
amount,
|
amount,
|
||||||
|
data,
|
||||||
from,
|
from,
|
||||||
gas,
|
gas,
|
||||||
gasPrice,
|
gasPrice,
|
||||||
@ -68,6 +71,7 @@ function mapDispatchToProps (dispatch) {
|
|||||||
},
|
},
|
||||||
update: ({
|
update: ({
|
||||||
amount,
|
amount,
|
||||||
|
data,
|
||||||
editingTransactionId,
|
editingTransactionId,
|
||||||
from,
|
from,
|
||||||
gas,
|
gas,
|
||||||
@ -78,6 +82,7 @@ function mapDispatchToProps (dispatch) {
|
|||||||
}) => {
|
}) => {
|
||||||
const editingTx = constructUpdatedTx({
|
const editingTx = constructUpdatedTx({
|
||||||
amount,
|
amount,
|
||||||
|
data,
|
||||||
editingTransactionId,
|
editingTransactionId,
|
||||||
from,
|
from,
|
||||||
gas,
|
gas,
|
||||||
|
@ -8,8 +8,9 @@ function addHexPrefixToObjectValues (obj) {
|
|||||||
}, {})
|
}, {})
|
||||||
}
|
}
|
||||||
|
|
||||||
function constructTxParams ({ selectedToken, to, amount, from, gas, gasPrice }) {
|
function constructTxParams ({ selectedToken, data, to, amount, from, gas, gasPrice }) {
|
||||||
const txParams = {
|
const txParams = {
|
||||||
|
data,
|
||||||
from,
|
from,
|
||||||
value: '0',
|
value: '0',
|
||||||
gas,
|
gas,
|
||||||
@ -21,13 +22,12 @@ function constructTxParams ({ selectedToken, to, amount, from, gas, gasPrice })
|
|||||||
txParams.to = to
|
txParams.to = to
|
||||||
}
|
}
|
||||||
|
|
||||||
const hexPrefixedTxParams = addHexPrefixToObjectValues(txParams)
|
return addHexPrefixToObjectValues(txParams)
|
||||||
|
|
||||||
return hexPrefixedTxParams
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function constructUpdatedTx ({
|
function constructUpdatedTx ({
|
||||||
amount,
|
amount,
|
||||||
|
data,
|
||||||
editingTransactionId,
|
editingTransactionId,
|
||||||
from,
|
from,
|
||||||
gas,
|
gas,
|
||||||
@ -36,9 +36,21 @@ function constructUpdatedTx ({
|
|||||||
to,
|
to,
|
||||||
unapprovedTxs,
|
unapprovedTxs,
|
||||||
}) {
|
}) {
|
||||||
|
const unapprovedTx = unapprovedTxs[editingTransactionId]
|
||||||
|
const txParamsData = unapprovedTx.txParams.data ? unapprovedTx.txParams.data : data
|
||||||
const editingTx = {
|
const editingTx = {
|
||||||
...unapprovedTxs[editingTransactionId],
|
...unapprovedTx,
|
||||||
txParams: addHexPrefixToObjectValues({ from, gas, gasPrice }),
|
txParams: Object.assign(
|
||||||
|
unapprovedTx.txParams,
|
||||||
|
addHexPrefixToObjectValues({
|
||||||
|
data: txParamsData,
|
||||||
|
to,
|
||||||
|
from,
|
||||||
|
gas,
|
||||||
|
gasPrice,
|
||||||
|
value: amount,
|
||||||
|
})
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedToken) {
|
if (selectedToken) {
|
||||||
@ -52,18 +64,10 @@ function constructUpdatedTx ({
|
|||||||
to: selectedToken.address,
|
to: selectedToken.address,
|
||||||
data,
|
data,
|
||||||
}))
|
}))
|
||||||
} else {
|
}
|
||||||
const { data } = unapprovedTxs[editingTransactionId].txParams
|
|
||||||
|
|
||||||
Object.assign(editingTx.txParams, addHexPrefixToObjectValues({
|
if (typeof editingTx.txParams.data === 'undefined') {
|
||||||
value: amount,
|
delete editingTx.txParams.data
|
||||||
to,
|
|
||||||
data,
|
|
||||||
}))
|
|
||||||
|
|
||||||
if (typeof editingTx.txParams.data === 'undefined') {
|
|
||||||
delete editingTx.txParams.data
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return editingTx
|
return editingTx
|
||||||
|
@ -129,6 +129,7 @@ describe('SendFooter Component', function () {
|
|||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
propsMethodSpies.update.getCall(0).args[0],
|
propsMethodSpies.update.getCall(0).args[0],
|
||||||
{
|
{
|
||||||
|
data: undefined,
|
||||||
amount: 'mockAmount',
|
amount: 'mockAmount',
|
||||||
editingTransactionId: 'mockEditingTransactionId',
|
editingTransactionId: 'mockEditingTransactionId',
|
||||||
from: 'mockAddress',
|
from: 'mockAddress',
|
||||||
@ -152,6 +153,7 @@ describe('SendFooter Component', function () {
|
|||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
propsMethodSpies.sign.getCall(0).args[0],
|
propsMethodSpies.sign.getCall(0).args[0],
|
||||||
{
|
{
|
||||||
|
data: undefined,
|
||||||
amount: 'mockAmount',
|
amount: 'mockAmount',
|
||||||
from: 'mockAddress',
|
from: 'mockAddress',
|
||||||
gas: 'mockGasLimit',
|
gas: 'mockGasLimit',
|
||||||
|
@ -38,6 +38,7 @@ proxyquire('../send-footer.container.js', {
|
|||||||
getSendTo: (s) => `mockTo:${s}`,
|
getSendTo: (s) => `mockTo:${s}`,
|
||||||
getSendToAccounts: (s) => `mockToAccounts:${s}`,
|
getSendToAccounts: (s) => `mockToAccounts:${s}`,
|
||||||
getTokenBalance: (s) => `mockTokenBalance:${s}`,
|
getTokenBalance: (s) => `mockTokenBalance:${s}`,
|
||||||
|
getSendHexData: (s) => `mockHexData:${s}`,
|
||||||
getUnapprovedTxs: (s) => `mockUnapprovedTxs:${s}`,
|
getUnapprovedTxs: (s) => `mockUnapprovedTxs:${s}`,
|
||||||
},
|
},
|
||||||
'./send-footer.selectors': { isSendFormInError: (s) => `mockInError:${s}` },
|
'./send-footer.selectors': { isSendFormInError: (s) => `mockInError:${s}` },
|
||||||
@ -51,6 +52,7 @@ describe('send-footer container', () => {
|
|||||||
it('should map the correct properties to props', () => {
|
it('should map the correct properties to props', () => {
|
||||||
assert.deepEqual(mapStateToProps('mockState'), {
|
assert.deepEqual(mapStateToProps('mockState'), {
|
||||||
amount: 'mockAmount:mockState',
|
amount: 'mockAmount:mockState',
|
||||||
|
data: 'mockHexData:mockState',
|
||||||
selectedToken: 'mockSelectedToken:mockState',
|
selectedToken: 'mockSelectedToken:mockState',
|
||||||
editingTransactionId: 'mockEditingTransactionId:mockState',
|
editingTransactionId: 'mockEditingTransactionId:mockState',
|
||||||
from: 'mockFromObject:mockState',
|
from: 'mockFromObject:mockState',
|
||||||
@ -100,6 +102,7 @@ describe('send-footer container', () => {
|
|||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
utilsStubs.constructTxParams.getCall(0).args[0],
|
utilsStubs.constructTxParams.getCall(0).args[0],
|
||||||
{
|
{
|
||||||
|
data: undefined,
|
||||||
selectedToken: {
|
selectedToken: {
|
||||||
address: '0xabc',
|
address: '0xabc',
|
||||||
},
|
},
|
||||||
@ -129,6 +132,7 @@ describe('send-footer container', () => {
|
|||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
utilsStubs.constructTxParams.getCall(0).args[0],
|
utilsStubs.constructTxParams.getCall(0).args[0],
|
||||||
{
|
{
|
||||||
|
data: undefined,
|
||||||
selectedToken: undefined,
|
selectedToken: undefined,
|
||||||
to: 'mockTo',
|
to: 'mockTo',
|
||||||
amount: 'mockAmount',
|
amount: 'mockAmount',
|
||||||
@ -160,6 +164,7 @@ describe('send-footer container', () => {
|
|||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
utilsStubs.constructUpdatedTx.getCall(0).args[0],
|
utilsStubs.constructUpdatedTx.getCall(0).args[0],
|
||||||
{
|
{
|
||||||
|
data: undefined,
|
||||||
to: 'mockTo',
|
to: 'mockTo',
|
||||||
amount: 'mockAmount',
|
amount: 'mockAmount',
|
||||||
from: 'mockFrom',
|
from: 'mockFrom',
|
||||||
|
@ -65,6 +65,28 @@ describe('send-footer utils', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('constructTxParams()', () => {
|
describe('constructTxParams()', () => {
|
||||||
|
it('should return a new txParams object with data if there data is given', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
constructTxParams({
|
||||||
|
data: 'someData',
|
||||||
|
selectedToken: false,
|
||||||
|
to: 'mockTo',
|
||||||
|
amount: 'mockAmount',
|
||||||
|
from: 'mockFrom',
|
||||||
|
gas: 'mockGas',
|
||||||
|
gasPrice: 'mockGasPrice',
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
data: '0xsomeData',
|
||||||
|
to: '0xmockTo',
|
||||||
|
value: '0xmockAmount',
|
||||||
|
from: '0xmockFrom',
|
||||||
|
gas: '0xmockGas',
|
||||||
|
gasPrice: '0xmockGasPrice',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it('should return a new txParams object with value and to properties if there is no selectedToken', () => {
|
it('should return a new txParams object with value and to properties if there is no selectedToken', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
constructTxParams({
|
constructTxParams({
|
||||||
@ -76,6 +98,7 @@ describe('send-footer utils', () => {
|
|||||||
gasPrice: 'mockGasPrice',
|
gasPrice: 'mockGasPrice',
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
|
data: undefined,
|
||||||
to: '0xmockTo',
|
to: '0xmockTo',
|
||||||
value: '0xmockAmount',
|
value: '0xmockAmount',
|
||||||
from: '0xmockFrom',
|
from: '0xmockFrom',
|
||||||
@ -96,6 +119,7 @@ describe('send-footer utils', () => {
|
|||||||
gasPrice: 'mockGasPrice',
|
gasPrice: 'mockGasPrice',
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
|
data: undefined,
|
||||||
value: '0x0',
|
value: '0x0',
|
||||||
from: '0xmockFrom',
|
from: '0xmockFrom',
|
||||||
gas: '0xmockGas',
|
gas: '0xmockGas',
|
||||||
|
@ -33,6 +33,7 @@ const selectors = {
|
|||||||
getSelectedTokenExchangeRate,
|
getSelectedTokenExchangeRate,
|
||||||
getSelectedTokenToFiatRate,
|
getSelectedTokenToFiatRate,
|
||||||
getSendAmount,
|
getSendAmount,
|
||||||
|
getSendHexData,
|
||||||
getSendEditingTransactionId,
|
getSendEditingTransactionId,
|
||||||
getSendErrors,
|
getSendErrors,
|
||||||
getSendFrom,
|
getSendFrom,
|
||||||
@ -210,6 +211,10 @@ function getSendAmount (state) {
|
|||||||
return state.metamask.send.amount
|
return state.metamask.send.amount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSendHexData (state) {
|
||||||
|
return state.metamask.send.data
|
||||||
|
}
|
||||||
|
|
||||||
function getSendEditingTransactionId (state) {
|
function getSendEditingTransactionId (state) {
|
||||||
return state.metamask.send.editingTransactionId
|
return state.metamask.send.editingTransactionId
|
||||||
}
|
}
|
||||||
|
@ -628,7 +628,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__to-autocomplete, &__memo-text-area {
|
&__to-autocomplete, &__memo-text-area, &__hex-data {
|
||||||
&__input {
|
&__input {
|
||||||
height: 54px;
|
height: 54px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -899,4 +899,4 @@
|
|||||||
|
|
||||||
.sliders-icon {
|
.sliders-icon {
|
||||||
color: $curious-blue;
|
color: $curious-blue;
|
||||||
}
|
}
|
||||||
|
@ -222,6 +222,14 @@ function reduceMetamask (state, action) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
case actions.UPDATE_SEND_HEX_DATA:
|
||||||
|
return extend(metamaskState, {
|
||||||
|
send: {
|
||||||
|
...metamaskState.send,
|
||||||
|
data: action.value,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
case actions.UPDATE_SEND_FROM:
|
case actions.UPDATE_SEND_FROM:
|
||||||
return extend(metamaskState, {
|
return extend(metamaskState, {
|
||||||
send: {
|
send: {
|
||||||
|
Loading…
Reference in New Issue
Block a user