diff --git a/app/actions/nftGalleryActions.js b/app/actions/nftGalleryActions.js index 8ed479193..04525f81f 100644 --- a/app/actions/nftGalleryActions.js +++ b/app/actions/nftGalleryActions.js @@ -23,14 +23,14 @@ export type NftGalleryItem = { export type NftGalleryResults = { results: NftGalleryItem[], + count: number, page: number, - hasMore: boolean, } const DEFAULT_NFT_GALLERY_RESULTS = (previousResults?: NftGalleryItem[]) => ({ results: previousResults ?? [], page: 0, - hasMore: false, + count: 0, }) export async function parseGhostMarketResults({ @@ -49,9 +49,9 @@ export async function parseGhostMarketResults({ `https://api.ghostmarket.io/api/v2/assets?chain=n3&owners[]=${address}&size=${SIZE}&page=${page}&getTotal=true`, ) - const { assets, next } = response?.data + const { assets, total: count } = response?.data - if (!assets || !assets.length) + if (!assets || !assets.length || !count) return DEFAULT_NFT_GALLERY_RESULTS(previousResults) const results = assets.map( @@ -70,11 +70,7 @@ export async function parseGhostMarketResults({ }), ) - return { - results: previousResults.concat(results), - page, - hasMore: !!next && assets.length === SIZE, - } + return { results: previousResults.concat(results), page, count } } catch (e) { console.error('An error occurred fetching data for NFT gallery', { e }) return DEFAULT_NFT_GALLERY_RESULTS(previousResults) diff --git a/app/components/Modals/TransferNftModal/TransferNftModal.jsx b/app/components/Modals/TransferNftModal/TransferNftModal.jsx index a2a2eb536..ec5717c03 100644 --- a/app/components/Modals/TransferNftModal/TransferNftModal.jsx +++ b/app/components/Modals/TransferNftModal/TransferNftModal.jsx @@ -4,6 +4,7 @@ import { FormattedMessage } from 'react-intl' import { wallet as n3Wallet } from '@cityofzion/neon-js' import { BSNeo3 } from '@cityofzion/bs-neo3' +import { NeonInvoker } from '@cityofzion/neon-invoker' import { NFT } from '../../../containers/NftGallery/NftGallery' import Button from '../../Button' import SelectInput from '../../Inputs/SelectInput' @@ -12,8 +13,6 @@ import N3Fees from '../../Send/N3Fees' import BaseModal from '../BaseModal' import styles from './TransferNftModal.scss' import { getNode, getRPCEndpoint } from '../../../actions/nodeStorageActions' -import N3Helper from '../../../util/N3Helper' -import { convertToArbitraryDecimals } from '../../../core/formatters' import { addPendingTransaction } from '../../../actions/pendingTransactionActions' import { useContactsContext } from '../../../context/contacts/ContactsContext' import { MODAL_TYPES } from '../../../core/constants' @@ -31,10 +30,10 @@ type Props = { address: string, tokenId: string, wif: string, - showSuccessNotification: ({ message: string }) => any, - showErrorNotification: ({ message: string }) => any, - showInfoNotification: ({ message: string }) => any, - hideNotification: (id: string) => void, + showSuccessNotification({ message: string }): any, + showErrorNotification({ message: string }): any, + showInfoNotification({ message: string, autoDismiss: number }): any, + hideNotification(id: string): any, dispatch: any => any, isHardwareLogin: boolean, signingFunction: () => void, @@ -52,14 +51,14 @@ export default function TransferNftModal(props: Props) { address, wif, dispatch, - isHardwareLogin, - signingFunction, showSuccessNotification, showErrorNotification, showInfoNotification, hideNotification, recipientAddressProp, publicKey, + isHardwareLogin, + signingFunction, } = props function handleSubmit() {} @@ -72,8 +71,7 @@ export default function TransferNftModal(props: Props) { recipientAddressProp ?? '', ) const [recipientAddressError, setRecipientAddressError] = useState('') - const [gasFee, setGasFee] = useState(DEFAULT_FEES) - const [feesInitialized, setFeesInitialized] = useState(false) + const [fees, setFees] = useState(DEFAULT_FEES) const [sendButtonDisabled, setSendButtonDisabled] = useState(false) const [loading, setLoading] = useState(true) const { contacts } = useContactsContext() @@ -160,53 +158,54 @@ export default function TransferNftModal(props: Props) { async function transfer() { try { setLoading(true) - let endpoint = await getNode(net) - if (!endpoint) { - endpoint = await getRPCEndpoint(net) + let rpcAddress = await getNode(net) + if (!rpcAddress) { + rpcAddress = await getRPCEndpoint(net) } const account = new n3Wallet.Account(isHardwareLogin ? publicKey : wif) - const testReq = { - params: { - request: { - method: 'multiInvoke', - params: { - invocations: [ - { - scriptHash: contract, - operation: 'transfer', - args: [ - { - type: 'Hash160', - value: recipientAddress, - }, - { type: 'ByteArray', value: tokenId }, - { type: 'Any', value: null }, - ], - }, - ], - signers: [{ scopes: 1 }], - }, - }, - }, - } - const results = await new N3Helper(endpoint, 0).rpcCall( + const invoker = await NeonInvoker.init({ + rpcAddress, account, - testReq, - isHardwareLogin, - signingFunction, - showInfoNotification, - hideNotification, - ) + signingCallback: signingFunction, + }) + + let notificationId + + if (isHardwareLogin) { + notificationId = showInfoNotification({ + message: 'Please sign the transaction on your hardware device', + autoDismiss: 0, + }) + } + + const hash = await invoker.invokeFunction({ + invocations: [ + { + scriptHash: contract, + operation: 'transfer', + args: [ + { + type: 'Hash160', + value: recipientAddress, + }, + { type: 'ByteArray', value: tokenId }, + { type: 'Any', value: null }, + ], + }, + ], + }) - const { result } = results + if (notificationId) { + hideNotification(notificationId) + } dispatch( addPendingTransaction.call({ address, net, tx: { - hash: result, + hash, sendEntries: [ { amount: 1, address, contractHash: contract, symbol: 'N/A' }, ], @@ -217,67 +216,52 @@ export default function TransferNftModal(props: Props) { showSuccessNotification({ message: 'Transaction pending! Your NFT will be transferred shortly.', }) - setLoading(false) - hideModal() } catch (e) { - hideModal() showErrorNotification({ message: e.message, }) + } finally { setLoading(false) + hideModal() } } - useEffect(() => { - async function testInvoke() { - setLoading(true) - let endpoint = await getNode(net) - if (!endpoint) { - endpoint = await getRPCEndpoint(net) - } - const account = new n3Wallet.Account(address) - const testReq = { - params: { - request: { - method: 'testInvoke', - params: { - invocations: [ + useEffect( + () => { + ;(async () => { + let rpcAddress = await getNode(net) + if (!rpcAddress) { + rpcAddress = await getRPCEndpoint(net) + } + const account = new n3Wallet.Account(isHardwareLogin ? publicKey : wif) + + const invoker = await NeonInvoker.init({ rpcAddress, account }) + const { networkFee, systemFee } = await invoker.calculateFee({ + invocations: [ + { + scriptHash: contract, + operation: 'transfer', + args: [ { - scriptHash: contract, - operation: 'transfer', - args: [ - { - type: 'Hash160', - value: address, - }, - { type: 'ByteArray', value: tokenId }, - { type: 'Any', value: null }, - ], + type: 'Hash160', + value: address, }, + { type: 'ByteArray', value: tokenId }, + { type: 'Any', value: null }, ], - signers: [{ scopes: 1 }], }, - }, - }, - } - const results = await new N3Helper(endpoint, 0).rpcCall( - account, - testReq, - isHardwareLogin, - signingFunction, - showInfoNotification, - hideNotification, - ) - const fee = convertToArbitraryDecimals(results.result.gasconsumed) - setGasFee({ - networkFee: fee, - systemFee: 0, - }) - setFeesInitialized(true) - setLoading(false) - } - testInvoke() - }, []) + ], + signers: [{ scopes: 1 }], + }) + + setFees({ + networkFee, + systemFee, + }) + })() + }, + [address, tokenId, isHardwareLogin, publicKey, wif, net, contract], + ) function createContactList(): Array { const filteredContacts = Object.keys(contacts).filter(contact => @@ -314,10 +298,7 @@ export default function TransferNftModal(props: Props) { error={recipientAddressError} /> - +