diff --git a/.env.example b/.env.example index 38a38642..40f2803b 100644 --- a/.env.example +++ b/.env.example @@ -10,11 +10,16 @@ ETHEREUM_NODE_WS=ws://localhost:8545 # Service Endpoints API_SERVICE_EXTERNAL=http://api.circles.local GRAPH_NODE_EXTERNAL=http://graph.circles.local +PATHFINDER_SERVICE_ENDPOINT=http://localhost:8081 RELAY_SERVICE_EXTERNAL=http://relay.circles.local # Database Endpoints DATABASE_SOURCE=graph +# Pathfinder Type 'cli' or 'server'. +# The core library can get the transfer steps from a pathfinder service ('server'), or from the circles-api that uses the cli tool ('cli') +PATHFINDER_TYPE=server + # Smart Contract addresses of 1.3.0 version HUB_ADDRESS=0xCfEB869F69431e42cdB54A4F4f105C19C080A601 PROXY_FACTORY_ADDRESS=0x9b1f7F645351AF3631a656421eD2e40f2802E6c0 diff --git a/locales/en.json b/locales/en.json index 79ffa221..c0ff60e8 100644 --- a/locales/en.json +++ b/locales/en.json @@ -340,7 +340,7 @@ "errorMessage": "Something went wrong .. {errorMessage}", "errorMessageCannotBeCalculated": "Maximum amount cannot be calculated at this time.", "errorMessageTransferInvalid": "Could not transfer Circles as it is invalid.", - "errorMessageTransferNotFound": "Could not transfer Circles as there is currently no complete trust path between @{username} and you ..", + "errorMessageTransferNotFound": "The transaction to @{username} could not be completed due to the trust paths. Try smaller amounts.", "errorMessageTransferTooComplex": "Could not transfer Circles as there are too many hops required to send Circles to @{username}. Consider sending a smaller amount and ask @{username} to trust you directly to make this transfer easier.", "errorMessageTransferUnknown": "Could not transfer Circles. Something went wrong!", "formAmount": "Enter amount", diff --git a/package-lock.json b/package-lock.json index 43dd5af2..3c2489a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6024,10 +6024,23 @@ "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, "requires": { "lru-cache": "^6.0.0" } + }, + "web3-utils": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.8.2.tgz", + "integrity": "sha512-v7j6xhfLQfY7xQDrUP0BKbaNrmZ2/+egbqP9q3KYmOiPpnvAfol+32slgL0WX/5n8VPvKCK5EZ1HGrAVICSToA==", + "requires": { + "bn.js": "^5.2.1", + "ethereum-bloom-filters": "^1.0.6", + "ethereumjs-util": "^7.1.0", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "utf8": "3.0.0" + } } } }, @@ -6360,6 +6373,18 @@ "web3-eth-abi": "1.8.2" }, "dependencies": { + "redux": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", + "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", + "dev": true, + "requires": { + "lodash": "^4.2.1", + "lodash-es": "^4.2.1", + "loose-envify": "^1.1.0", + "symbol-observable": "^1.0.3" + } + }, "redux": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", @@ -6551,6 +6576,18 @@ "web3": "1.8.2" }, "dependencies": { + "ethereumjs-util": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", + "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", + "requires": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.2.4" + } + }, "web3": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/web3/-/web3-1.8.2.tgz", @@ -6594,6 +6631,20 @@ "dev": true, "optional": true }, + "ethereumjs-util": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", + "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", + "dev": true, + "optional": true, + "requires": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.2.4" + } + }, "web3": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/web3/-/web3-1.8.2.tgz", @@ -14248,6 +14299,31 @@ "module-error": "^1.0.1" } }, + "level-concat-iterator": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz", + "integrity": "sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ==", + "dev": true, + "requires": { + "catering": "^2.1.0" + } + }, + "level-supports": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-2.1.0.tgz", + "integrity": "sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA==", + "dev": true + }, + "level-transcoder": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/level-transcoder/-/level-transcoder-1.0.1.tgz", + "integrity": "sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==", + "dev": true, + "requires": { + "buffer": "^6.0.3", + "module-error": "^1.0.1" + } + }, "leveldown": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-6.1.0.tgz", diff --git a/src/components/ButtonWobbly.js b/src/components/ButtonWobbly.js index b231b1a7..f77fc6e2 100644 --- a/src/components/ButtonWobbly.js +++ b/src/components/ButtonWobbly.js @@ -56,7 +56,6 @@ const ButtonWobbly = ({ isReady, isPending, onClick, - to, }) => { const classes = useStyles(); const IconElement = iconSelector(icon); diff --git a/src/store/token/actions.js b/src/store/token/actions.js index 74e9e66d..c92583ca 100644 --- a/src/store/token/actions.js +++ b/src/store/token/actions.js @@ -315,30 +315,41 @@ export function transfer( const value = new web3.utils.BN( core.utils.toFreckles(tcToCrc(Date.now(), Number(amount))), ); - const txHash = await loopTransfer( - from, - to, - value, - paymentNote, - hops, - attempts, - ); + let txHash; - dispatch( - addPendingActivity({ - txHash, - type: ActivityTypes.HUB_TRANSFER, - data: { - from, - to, - value: value.toString(), - }, - }), - ); + if (process.env.PATHFINDER_TYPE === 'cli') { + txHash = await loopTransfer( + from, + to, + value, + paymentNote, + hops, + attempts, + ); + } else { + txHash = await core.token.transfer(from, to, value, paymentNote); + } - dispatch({ - type: ActionTypes.TOKEN_TRANSFER_SUCCESS, - }); + if (txHash !== null) { + dispatch( + addPendingActivity({ + txHash, + type: ActivityTypes.HUB_TRANSFER, + data: { + from, + to, + value: value.toString(), + }, + }), + ); + + dispatch({ + type: ActionTypes.TOKEN_TRANSFER_SUCCESS, + }); + } else { + // "TransactionServiceException: execution reverted" as an example coming from core.token.transfer + throw new TransferError(); + } } catch (error) { dispatch({ type: ActionTypes.TOKEN_TRANSFER_ERROR, diff --git a/src/utils/findPath.js b/src/utils/findPath.js index b3cbe6ed..acaed875 100644 --- a/src/utils/findPath.js +++ b/src/utils/findPath.js @@ -11,7 +11,7 @@ const LARGE_AMOUNT = new web3.utils.BN( web3.utils.toWei('1000000000000000', 'ether'), ); -// Recursive helper function for findMaxFlow +// Recursive helper function for findMaxFlow recursively reducing number of hops async function loopFindMaxFlow( from, to, @@ -60,14 +60,26 @@ async function loopFindMaxFlow( * @returns nothing. Updates MaxFlow state in Freckles. */ export async function findMaxFlow(from, to, setMaxFlow) { - // First attempting via API + // First attempting via API. + // The API parameters depends on the Pathfinder Type in use: + // The 'cli' uses hops, but this option is not available in the 'server'. + // Therefore we set the attemptsLeft and the hops option will be ignored. try { - const response = await loopFindMaxFlow( - from, - to, - PATHFINDER_HOPS_DEFAULT, - PATHFINDER_HOPS_DEFAULT, - ); + let response; + if (process.env.PATHFINDER_TYPE === 'cli') { + response = await loopFindMaxFlow( + from, + to, + PATHFINDER_HOPS_DEFAULT, + PATHFINDER_HOPS_DEFAULT, + ); + } else { + response = await core.token.findTransitiveTransfer( + from, + to, + LARGE_AMOUNT, + ); + } // Throw an error when no path was found, we should try again with // checking direct sends as the API might not be in sync yet diff --git a/src/views/SendConfirm.js b/src/views/SendConfirm.js index 0b1fcc26..591c92a5 100644 --- a/src/views/SendConfirm.js +++ b/src/views/SendConfirm.js @@ -152,6 +152,8 @@ const SendConfirm = () => { messageId = 'Invalid'; } else if (error.code === ErrorCodes.TRANSFER_NOT_FOUND) { messageId = 'NotFound'; + } else if (error.code === ErrorCodes.UNKNOWN_ERROR) { + messageId = 'Unknown'; } text = translate('SendConfirm.errorMessageTransfer' + messageId, { amount,