diff --git a/.github/workflows/check-PRs.yml b/.github/workflows/check-PRs.yml index cfd28bf3a..77de5dd15 100644 --- a/.github/workflows/check-PRs.yml +++ b/.github/workflows/check-PRs.yml @@ -18,6 +18,45 @@ jobs: npm ci npm run lint + e2e-test: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@master + - uses: actions/setup-node@v1 + with: + node-version: '14.17.0' + + - name: Start Containers + run: | + docker-compose build + ./start-nightfall -g &> e2e-test.log &disown + + - name: wait 1000s for Containers startup and setup completion + run: sleep 1000 + + - name: debug logs - after container startup + if: always() + run: cat e2e-test.log + + - name: Run integration test + run: | + npm ci + npm run test-e2e + + - name: debug logs - after integration test run + if: always() + run: cat e2e-test.log + + - name: If integration test failed, shutdown the Containers + if: failure() + run: docker-compose -f docker-compose.yml -f docker-compose.ganache.yml down -v + + - name: If integration test failed, upload logs files as artifacts + if: failure() + uses: actions/upload-artifact@master + with: + name: e2e-test-logs + path: ./e2e-test.log ganache-test: runs-on: ubuntu-18.04 steps: diff --git a/README.md b/README.md index 62dfca69d..c100d1629 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,6 @@ More information can be found [here](https://github.com/EYBlockchain/nightfall_3 1. Open Metamask in browser 2. Settings->Advance->Reset Account -- Transactions with ERC721 and ERC1155 tokens do not work. This is because there is not way yet to recover the token Id. - Direct transactions are not implemented - Instant withdraw is selected when doing a withdraw only. Once submitted the instant withdraw request,the wallet requests a simple withdraw and inmediatelly after converts this withdraw into an instant withdraw. Wallet will attempt to send the instant withdraw request up to 10 times, once every 10 seconds. It is likely that during this period, you need to request a simpler transaction (deposit, withdraw or transfer) so that the original withdraw is processed by the processor and the instant withdraw can be carried out. - Tested with node version v14.18.0 diff --git a/cli/lib/abi.mjs b/cli/lib/abi.mjs index 5e13d591c..9c2f1e619 100644 --- a/cli/lib/abi.mjs +++ b/cli/lib/abi.mjs @@ -2,6 +2,7 @@ import { TOKEN_TYPE } from './constants.mjs'; import ERC20ABI from './abis/ERC20.mjs'; import ERC721ABI from './abis/ERC721.mjs'; import ERC1155ABI from './abis/ERC1155.mjs'; +import ERC165 from './abis/ERC165.mjs'; function getAbi(tokenType) { switch (tokenType) { @@ -11,7 +12,8 @@ function getAbi(tokenType) { return ERC721ABI; case TOKEN_TYPE.ERC1155: return ERC1155ABI; - + case TOKEN_TYPE.ERC165: + return ERC165; default: return null; } diff --git a/cli/lib/abis/ERC165.mjs b/cli/lib/abis/ERC165.mjs new file mode 100644 index 000000000..ff933f093 --- /dev/null +++ b/cli/lib/abis/ERC165.mjs @@ -0,0 +1,21 @@ +export default [ + { + inputs: [ + { + internalType: 'bytes4', + name: 'interfaceId', + type: 'bytes4', + }, + ], + name: 'supportsInterface', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'view', + type: 'function', + }, +]; diff --git a/cli/lib/nf3.mjs b/cli/lib/nf3.mjs index b6cff5581..9252c41eb 100644 --- a/cli/lib/nf3.mjs +++ b/cli/lib/nf3.mjs @@ -396,17 +396,15 @@ class Nf3 { @param {number} fee - the amount being paid for the instant withdrawal service */ async requestInstantWithdrawal(withdrawTransactionHash, fee) { - // find the L2 block containing the L2 transaction hash - let res = await axios.get( - `${this.optimistBaseUrl}/block/transaction-hash/${withdrawTransactionHash}`, - ); - const { block } = res.data; - if (!block) return null; // block not found - // set the instant withdrawal fee - res = await axios.post(`${this.clientBaseUrl}/set-instant-withdrawal`, { - transactionHash: withdrawTransactionHash, - }); - return this.submitTransaction(res.data.txDataToSign, this.shieldContractAddress, fee); + try { + // set the instant withdrawal fee + const res = await axios.post(`${this.clientBaseUrl}/set-instant-withdrawal`, { + transactionHash: withdrawTransactionHash, + }); + return this.submitTransaction(res.data.txDataToSign, this.shieldContractAddress, fee); + } catch { + return null; + } } /** @@ -696,43 +694,32 @@ class Nf3 { } /** - Get if it's a valid withdraw transaction for finalising the - withdrawal of funds to L1 (only relevant for ERC20). + Returns the balance of tokens held in layer 2 @method @async - @param {string} withdrawTransactionHash - the hash of the Layer 2 transaction in question + @returns {Promise} This promise rosolves into an object whose properties are the + addresses of the ERC contracts of the tokens held by this account in Layer 2. The + value of each propery is the number of tokens originating from that contract. */ - async isValidWithdrawal(withdrawTransactionHash) { - let res; - let valid = false; - - res = await axios.get( - `${this.optimistBaseUrl}/block/transaction-hash/${withdrawTransactionHash}`, - ); - const { block, transactions, index } = res.data; - - if (block) { - res = await axios.post(`${this.clientBaseUrl}/valid-withdrawal`, { - block, - transactions, - index, - }); - valid = res.data.valid; - } - - return valid; + async getLayer2Balances() { + const res = await axios.get(`${this.clientBaseUrl}/commitment/balance`); + return res.data.balance; } /** - Returns the balance of tokens held in layer 2 + Returns the balance details of tokens held in layer 2 @method @async + @param {Array} ercList - list of erc contract addresses to filter. @returns {Promise} This promise rosolves into an object whose properties are the addresses of the ERC contracts of the tokens held by this account in Layer 2. The value of each propery is the number of tokens originating from that contract. */ - async getLayer2Balances() { - const res = await axios.get(`${this.clientBaseUrl}/commitment/balance`); + async getLayer2BalancesDetails(ercList) { + const res = await axios.post(`${this.clientBaseUrl}/commitment/balance-details`, { + compressedPkd: this.zkpKeys.compressedPkd, + ercList, + }); return res.data.balance; } @@ -770,7 +757,7 @@ class Nf3 { if (typeof window !== 'undefined') { if (window.ethereum && this.ethereumSigningKey === '') { this.web3 = new Web3(window.ethereum); - window.ethereum.send('eth_requestAccounts'); + window.ethereum.request({ method: 'eth_accounts' }); } else { // Metamask not available throw new Error('No Web3 provider found'); diff --git a/cli/lib/tokens.mjs b/cli/lib/tokens.mjs index aadb13516..051cd6648 100644 --- a/cli/lib/tokens.mjs +++ b/cli/lib/tokens.mjs @@ -80,43 +80,141 @@ Get Information of ERC token in ethereum address. Default is in Wei * @param {object} options - different options for tokens. For ERC20, toEth is boolean * to return the balance as Ether. For ERC1155, tokenId is required to get balance * of specific token Id -* @returns {Object} {balance, decimals} +* @returns {Object} {balance, decimals, tokenType, details} */ async function getERCInfo(ercAddress, ethereumAddress, provider, options) { let toEth; let tokenId; + let details; + let tokenTypeFilter; + if (typeof options !== 'undefined') { toEth = options.toEth; tokenId = options.tokenId; + details = options.details; + tokenTypeFilter = options.tokenType; + } + + let tokenType; + let balance; + let decimals = 0; + const tokenIds = []; + + if (tokenTypeFilter) { + switch (tokenTypeFilter.toUpperCase()) { + case 'ERC721': + tokenType = TOKEN_TYPE.ERC721; + break; + case 'ERC1155': + tokenType = TOKEN_TYPE.ERC1155; + break; + case 'ERC20': + tokenType = TOKEN_TYPE.ERC20; + break; + default: + throw new Error(`Unknown ERC token ${tokenTypeFilter}`); + } + } else { + try { + // Check supportsInterface ERC165 that implements ERC721 and ERC1155 + const abi = getAbi(TOKEN_TYPE.ERC165); + const ercContract = new provider.eth.Contract(abi, ercAddress); + const interface721 = await ercContract.methods.supportsInterface('0x80ac58cd').call(); // ERC721 interface + if (interface721) { + tokenType = TOKEN_TYPE.ERC721; + } else { + const interface1155 = await ercContract.methods.supportsInterface('0xd9b67a26').call(); // ERC1155 interface + if (interface1155) tokenType = TOKEN_TYPE.ERC1155; + } + } catch { + // Expected ERC20 + tokenType = TOKEN_TYPE.ERC20; + } } - try { - const abi = getAbi(TOKEN_TYPE.ERC20); + if (tokenType === TOKEN_TYPE.ERC721) { + // ERC721 + const abi = getAbi(TOKEN_TYPE.ERC721); const ercContract = new provider.eth.Contract(abi, ercAddress); - let balance = await ercContract.methods.balanceOf(ethereumAddress).call(); - const decimals = await getDecimals(ercAddress, TOKEN_TYPE.ERC20, provider); - if (toEth) { - balance = fromBaseUnit(balance, decimals); + balance = await ercContract.methods.balanceOf(ethereumAddress).call(); + + if (details) { + const incomingTokenTransferEvents = await ercContract.getPastEvents('Transfer', { + filter: { to: ethereumAddress }, + fromBlock: 0, + toBlock: 'latest', + }); + const tokenIdsEvents = []; + incomingTokenTransferEvents.forEach(event => { + if (!tokenIdsEvents.includes(event.returnValues.tokenId)) + tokenIdsEvents.push(event.returnValues.tokenId); + }); + + await Promise.all( + tokenIdsEvents.map(async tkId => { + const ownerTokenId = await ercContract.methods.ownerOf(tkId).call(); + if (ownerTokenId === ethereumAddress) tokenIds.push({ tokenId: tkId, amount: '1' }); + }), + ); } - return { balance, decimals, tokenType: TOKEN_TYPE.ERC20 }; - } catch { + } else if (tokenType === TOKEN_TYPE.ERC1155) { + // ERC1155 + const abi = getAbi(TOKEN_TYPE.ERC1155); + const ercContract = new provider.eth.Contract(abi, ercAddress); + if (!tokenId) tokenId = 0; + balance = await ercContract.methods.balanceOf(ethereumAddress, tokenId).call(); + if (details) { + const incomingTokenTransferBatchEvents = await ercContract.getPastEvents('TransferBatch', { + filter: {}, + fromBlock: 0, + toBlock: 'latest', + }); + const tokenIdsEvents = []; + incomingTokenTransferBatchEvents.forEach(event => { + event.returnValues.ids.forEach(id => { + if (!tokenIdsEvents.includes(id)) tokenIdsEvents.push(id); + }); + }); + + const incomingTokenTransferSingleEvents = await ercContract.getPastEvents('TransferSingle', { + filter: {}, + fromBlock: 0, + toBlock: 'latest', + }); + incomingTokenTransferSingleEvents.forEach(event => { + if (!tokenIdsEvents.includes(event.returnValues.id)) + tokenIdsEvents.push(event.returnValues.id); + }); + + await Promise.all( + tokenIdsEvents.map(async Id => { + const amount = await ercContract.methods.balanceOf(ethereumAddress, Id).call(); + tokenIds.push({ tokenId: Id, amount }); + }), + ); + + balance = tokenIds + .reduce((partialSum, tokenIdInfo) => partialSum + BigInt(tokenIdInfo.amount), BigInt(0)) + .toString(); + } + } else { + // expected ERC20 try { - const abi = getAbi(TOKEN_TYPE.ERC1155); + const abi = getAbi(TOKEN_TYPE.ERC20); const ercContract = new provider.eth.Contract(abi, ercAddress); - const balance = await ercContract.methods.balanceOf(ethereumAddress, tokenId).call(); - return { balance, tokenType: TOKEN_TYPE.ERC1155 }; + balance = await ercContract.methods.balanceOf(ethereumAddress).call(); + decimals = await getDecimals(ercAddress, TOKEN_TYPE.ERC20, provider); + if (toEth) balance = fromBaseUnit(balance, decimals); + if (details) tokenIds.push({ tokenId: 0, amount: balance }); } catch { - try { - const abi = getAbi(TOKEN_TYPE.ERC721); - const ercContract = new provider.eth.Contract(abi, ercAddress); - const balance = await ercContract.methods.balanceOf(ethereumAddress).call(); - return { balance, tokenType: TOKEN_TYPE.ERC721 }; - } catch { - // TODO - throw new Error('Unknown token type', ercAddress); - } + throw new Error('Unknown token type', ercAddress); } } + + let result = { balance, tokenType, details: tokenIds }; + if (tokenType === TOKEN_TYPE.ERC20) result = { ...result, decimals }; + else result = { ...result, decimals: 0 }; + return result; } export { approve, getDecimals, getERCInfo }; diff --git a/doc/lib/nf3.mjs.html b/doc/lib/nf3.mjs.html index 65c355260..2e2abf602 100644 --- a/doc/lib/nf3.mjs.html +++ b/doc/lib/nf3.mjs.html @@ -27,12 +27,16 @@

Source: nf3.mjs

import axios from 'axios';
+import axios from 'axios';
 import Web3 from 'web3';
 import WebSocket from 'ws';
 import EventEmitter from 'events';
 import { Mutex } from 'async-mutex';
-import { generateMnemonic } from 'bip39';
-
+import { approve } from './tokens.mjs';
+import erc20 from './abis/ERC20.mjs';
+import erc721 from './abis/ERC721.mjs';
+import erc1155 from './abis/ERC1155.mjs';
+import { ENVIRONMENTS } from './constants.mjs';
 
 /**
 @class
@@ -83,20 +87,20 @@ 

Source: nf3.mjs

latestWithdrawHash; - constructor( - clientBaseUrl, - optimistBaseUrl, - optimistWsUrl, - web3WsUrl, - ethereumSigningKey, - zkpKeys, - ) { - this.clientBaseUrl = clientBaseUrl; - this.optimistBaseUrl = optimistBaseUrl; - this.optimistWsUrl = optimistWsUrl; + mnemonic = {}; + + contracts = { ERC20: erc20, ERC721: erc721, ERC1155: erc1155 }; + + currentEnvironment; + + constructor(web3WsUrl, ethereumSigningKey, environment = ENVIRONMENTS.localhost, zkpKeys) { + this.clientBaseUrl = environment.clientApiUrl; + this.optimistBaseUrl = environment.optimistApiUrl; + this.optimistWsUrl = environment.optimistWsUrl; this.web3WsUrl = web3WsUrl; this.ethereumSigningKey = ethereumSigningKey; this.zkpKeys = zkpKeys; + this.currentEnvironment = environment; } /** @@ -104,21 +108,20 @@

Source: nf3.mjs

blockchain. @returns {Promise} */ - async init() { - this.web3 = new Web3(this.web3WsUrl); - // Generate a random mnemonic (uses crypto.randomBytes under the hood), defaults to 128-bits of entropy - const mnemonic = generateMnemonic(); - this.zkpKeys = this.zkpKeys || (await axios.post(`${this.clientBaseUrl}/generate-keys`), { mnemonic, path: `m/44'/60'/0'/0` }).data; + async init(mnemonic) { + this.setWeb3Provider(); this.shieldContractAddress = await this.getContractAddress('Shield'); this.proposersContractAddress = await this.getContractAddress('Proposers'); this.challengesContractAddress = await this.getContractAddress('Challenges'); this.stateContractAddress = await this.getContractAddress('State'); // set the ethereumAddress iff we have a signing key - if (this.ethereumSigningKey) - this.ethereumAddress = this.web3.eth.accounts.privateKeyToAccount( - this.ethereumSigningKey, - ).address; - return this.subscribeToIncomingViewingKeys(); + if (typeof this.ethereumSigningKey === 'string') { + this.ethereumAddress = await this.getAccounts(); + } + // set zkp keys from mnemonic if provided + if (typeof mnemonic !== 'undefined') { + await this.setzkpKeysFromMnemonic(mnemonic, 0); + } } /** @@ -127,11 +130,9 @@

Source: nf3.mjs

@method @param {string} key - the ethereum private key as a hex string. */ - setEthereumSigningKey(key) { + async setEthereumSigningKey(key) { this.ethereumSigningKey = key; - this.ethereumAddress = this.web3.eth.accounts.privateKeyToAccount( - this.ethereumSigningKey, - ).address; + this.ethereumAddress = await this.getAccounts(); // clear the nonce as we're using a fresh account this.nonce = 0; } @@ -144,6 +145,28 @@

Source: nf3.mjs

*/ setzkpKeys(keys) { this.zkpKeys = keys; + return this.subscribeToIncomingViewingKeys(); + } + + /** + Setter for the zkp keys by mnemonic, in case it wasn't known at build time and we don't + want to use autogenerated ones. + @method + @param {string} mnemonic - 12 word phrase + @param {number} addressIndex - Index used to generate keys combined with mnemonic + */ + async setzkpKeysFromMnemonic(mnemonic, addressIndex) { + if (mnemonic !== '') { + this.mnemonic.phrase = mnemonic; + } + this.mnemonic.addressIndex = addressIndex.toString(); + this.zkpKeys = ( + await axios.post(`${this.clientBaseUrl}/generate-keys`, { + mnemonic: this.mnemonic.phrase, + path: `m/44'/60'/0'/${this.mnemonic.addressIndex}`, + }) + ).data; + return this.subscribeToIncomingViewingKeys(); } /** @@ -164,22 +187,34 @@

Source: nf3.mjs

) { // We'll manage the nonce ourselves because we can run too fast for the blockchain client to update // we need a Mutex so that we don't get a nonce-updating race. + let tx; await this.nonceMutex.runExclusive(async () => { // if we don't have a nonce, we must get one from the ethereum client if (!this.nonce) this.nonce = await this.web3.eth.getTransactionCount(this.ethereumAddress); + + let gasPrice = 10000000000; + const gas = (await this.web3.eth.getBlock('latest')).gasLimit; + const blockGasPrice = Number(await this.web3.eth.getGasPrice()); + if (blockGasPrice > gasPrice) gasPrice = blockGasPrice; + tx = { + from: this.ethereumAddress, to: contractAddress, data: unsignedTransaction, value: fee, - gas: 10000000, - gasPrice: 10000000000, + gas, + gasPrice, nonce: this.nonce, }; this.nonce++; }); - const signed = await this.web3.eth.accounts.signTransaction(tx, this.ethereumSigningKey); - return this.web3.eth.sendSignedTransaction(signed.rawTransaction); + + if (this.ethereumSigningKey) { + const signed = await this.web3.eth.accounts.signTransaction(tx, this.ethereumSigningKey); + return this.web3.eth.sendSignedTransaction(signed.rawTransaction); + } + return this.web3.eth.sendTransaction(tx); } /** @@ -243,6 +278,15 @@

Source: nf3.mjs

@returns {Promise} Resolves into the Ethereum transaction receipt. */ async deposit(ercAddress, tokenType, value, tokenId, fee = this.defaultFee) { + await approve( + ercAddress, + this.ethereumAddress, + this.shieldContractAddress, + tokenType, + value, + this.web3, + ); + const res = await axios.post(`${this.clientBaseUrl}/deposit`, { ercAddress, tokenId, @@ -362,14 +406,8 @@

Source: nf3.mjs

*/ async finaliseWithdrawal(withdrawTransactionHash) { // find the L2 block containing the L2 transaction hash - let res = await axios.get( - `${this.optimistBaseUrl}/block/transaction-hash/${withdrawTransactionHash}`, - ); - const { block, transactions, index } = res.data; - res = await axios.post(`${this.clientBaseUrl}/finalise-withdrawal`, { - block, - transactions, - index, + const res = await axios.post(`${this.clientBaseUrl}/finalise-withdrawal`, { + transactionHash: withdrawTransactionHash, }); return this.submitTransaction(res.data.txDataToSign, this.shieldContractAddress, 0); } @@ -383,18 +421,15 @@

Source: nf3.mjs

@param {number} fee - the amount being paid for the instant withdrawal service */ async requestInstantWithdrawal(withdrawTransactionHash, fee) { - // find the L2 block containing the L2 transaction hash - let res = await axios.get( - `${this.optimistBaseUrl}/block/transaction-hash/${withdrawTransactionHash}`, - ); - const { block, transactions, index } = res.data; - // set the instant withdrawal fee - res = await axios.post(`${this.clientBaseUrl}/set-instant-withdrawal`, { - block, - transactions, - index, - }); - return this.submitTransaction(res.data.txDataToSign, this.shieldContractAddress, fee); + try { + // set the instant withdrawal fee + const res = await axios.post(`${this.clientBaseUrl}/set-instant-withdrawal`, { + transactionHash: withdrawTransactionHash, + }); + return this.submitTransaction(res.data.txDataToSign, this.shieldContractAddress, fee); + } catch { + return null; + } } /** @@ -500,6 +535,21 @@

Source: nf3.mjs

return this.submitTransaction(res.data.txDataToSign, this.proposersContractAddress, 0); } + /** + Change current proposer. + It will use the address of the Ethereum Signing key that is holds to change the current + proposer. + @method + @async + @returns {Promise} A promise that resolves to the Ethereum transaction receipt. + */ + async changeCurrentProposer() { + const res = await axios.get(`${this.optimistBaseUrl}/proposer/change`, { + address: this.ethereumAddress, + }); + return this.submitTransaction(res.data.txDataToSign, this.proposersContractAddress, 0); + } + /** Withdraw the bond left by the proposer. It will use the address of the Ethereum Signing key that is holds to withdraw the bond. @@ -668,39 +718,6 @@

Source: nf3.mjs

return newChallengeEmitter; } - /** - Get if it's a valid withdraw transaction for finalising the - withdrawal of funds to L1 (only relevant for ERC20). - @method - @async - @param {string} withdrawTransactionHash - the hash of the Layer 2 transaction in question - */ - async isValidWithdrawal(withdrawTransactionHash) { - let res; - let valid = false; - - try { - res = await axios.get( - `${this.optimistBaseUrl}/block/transaction-hash/${withdrawTransactionHash}`, - ); - } catch (e) { - // transaction is not in block yet - valid = false; - } - - if (res) { - const { block, transactions, index } = res.data; - res = await axios.post(`${this.clientBaseUrl}/valid-withdrawal`, { - block, - transactions, - index, - }); - valid = res.data.valid; - } - - return valid; - } - /** Returns the balance of tokens held in layer 2 @method @@ -737,40 +754,22 @@

Source: nf3.mjs

*/ async getPendingWithdraws() { const res = await axios.get(`${this.clientBaseUrl}/commitment/withdraws`); - const listWithdrawCommitments = res.data.commitments[this.zkpKeys.compressedPkd]; - const pendingWithdrawCommitments = []; - if (listWithdrawCommitments) { - // we loop through all ercaddresses in the wallet - const ercAddresses = Object.getOwnPropertyNames(listWithdrawCommitments); - - for (let i = 0; i < ercAddresses.length; i++) { - for (let k = 0; k < listWithdrawCommitments[ercAddresses[i]].length; k++) { - // eslint-disable-next-line no-await-in-loop - const valid = await this.isValidWithdrawal( - listWithdrawCommitments[ercAddresses[i]][k].transactionNullified.transactionHash, - ); - pendingWithdrawCommitments.push({ - commitment: listWithdrawCommitments[ercAddresses[i]][k], - valid, - }); - } - } - } - return pendingWithdrawCommitments; + return res.data.commitments; } /** Set a Web3 Provider URL - @param {String|Object} providerData - Network url (i.e, http://localhost:8544) or an Object with the information to set the provider */ - setWeb3Provider(providerData) { - if (typeof providerData === 'string' || typeof window === 'undefined') { - this.web3 = new Web3(providerData); - } - - if (typeof window !== 'undefined' && window.ethereum) { - this.web3 = new Web3(window.ethereum); - window.ethereum.send('eth_requestAccounts'); + setWeb3Provider() { + this.web3 = new Web3(this.web3WsUrl); + if (typeof window !== 'undefined') { + if (window.ethereum && this.ethereumSigningKey === '') { + this.web3 = new Web3(window.ethereum); + window.ethereum.send('eth_requestAccounts'); + } else { + // Metamask not available + throw new Error('No Web3 provider found'); + } } } @@ -813,6 +812,9 @@

Source: nf3.mjs

@returns {Promise} - string with the signature */ signMessage(msg, account) { + if (this.ethereumSigningKey) { + return this.web3.eth.accounts.sign(msg, this.ethereumSigningKey).signature; + } return this.web3.eth.personal.sign(msg, account); } @@ -826,6 +828,7 @@

Source: nf3.mjs

} export default Nf3; +
diff --git a/nightfall-client/src/routes/commitment.mjs b/nightfall-client/src/routes/commitment.mjs index 97e43ef2b..7af345a64 100644 --- a/nightfall-client/src/routes/commitment.mjs +++ b/nightfall-client/src/routes/commitment.mjs @@ -9,6 +9,7 @@ import { getWalletBalance, getWalletCommitments, getWithdrawCommitments, + getWalletBalanceDetails, } from '../services/commitment-storage.mjs'; const router = express.Router(); @@ -38,6 +39,18 @@ router.get('/balance', async (req, res, next) => { } }); +router.post('/balance-details', async (req, res, next) => { + logger.debug('commitment/balance details endpoint received GET'); + try { + const { compressedPkd, ercList } = req.body; + const balance = await getWalletBalanceDetails(compressedPkd, ercList); + res.json({ balance }); + } catch (err) { + logger.error(err); + next(err); + } +}); + router.get('/commitments', async (req, res, next) => { logger.debug('commitment/commitments endpoint received GET'); try { diff --git a/nightfall-client/src/services/commitment-storage.mjs b/nightfall-client/src/services/commitment-storage.mjs index 788e39cee..47bc02231 100644 --- a/nightfall-client/src/services/commitment-storage.mjs +++ b/nightfall-client/src/services/commitment-storage.mjs @@ -241,6 +241,70 @@ export async function getWalletBalance() { }, {}); } +// function to get the balance of commitments for each ERC address +export async function getWalletBalanceDetails(compressedPkd, ercList) { + let ercAddressList = ercList || []; + ercAddressList = ercAddressList.map(e => e.toUpperCase()); + const connection = await mongo.connection(MONGO_URL); + const db = connection.db(COMMITMENTS_DB); + const query = { isNullified: false, isOnChain: { $gte: 0 } }; + const options = { + projection: { + preimage: { ercAddress: 1, compressedPkd: 1, tokenId: 1, value: 1 }, + _id: 0, + }, + }; + const wallet = await db.collection(COMMITMENTS_COLLECTION).find(query, options).toArray(); + // the below is a little complex. First we extract the ercAddress, tokenId and value + // from the preimage. Then we format them nicely. We don't care about the value of the + // tokenId, other than if it's zero or not (indicating the token type). Then we filter + // any commitments of zero value and tokenId (meaningless commitments), then we + // work out the balance contribution of each commitment - a 721 token has no value field in the + // commitment but each 721 token counts as a balance of 1. Then finally add up the individual + // commitment balances to get a balance for each erc address. + const res1 = wallet.map(e => ({ + ercAddress: `0x${BigInt(e.preimage.ercAddress).toString(16).padStart(40, '0')}`, // Pad this to actual address length + compressedPkd: e.preimage.compressedPkd, + tokenId: !!BigInt(e.preimage.tokenId), + value: Number(BigInt(e.preimage.value)), + id: Number(BigInt(e.preimage.tokenId)), + })); + console.log('RES: ', res1); + + const res = wallet + .map(e => ({ + ercAddress: `0x${BigInt(e.preimage.ercAddress).toString(16).padStart(40, '0')}`, // Pad this to actual address length + compressedPkd: e.preimage.compressedPkd, + tokenId: !!BigInt(e.preimage.tokenId), + value: Number(BigInt(e.preimage.value)), + id: Number(BigInt(e.preimage.tokenId)), + })) + .filter( + e => + (e.tokenId || e.value > 0) && + e.compressedPkd === compressedPkd && + (ercAddressList.length === 0 || ercAddressList.includes(e.ercAddress.toUpperCase())), + ) // there should be no commitments with tokenId and value of ZERO + .map(e => ({ + compressedPkd: e.compressedPkd, + ercAddress: e.ercAddress, + balance: e.tokenId ? 1 : e.value, + tokenId: e.id, + })) + .reduce((acc, e) => { + if (!acc[e.compressedPkd]) acc[e.compressedPkd] = {}; + if (!acc[e.compressedPkd][e.ercAddress]) acc[e.compressedPkd][e.ercAddress] = []; + if (e.tokenId === 0 && acc[e.compressedPkd][e.ercAddress].length > 0) { + acc[e.compressedPkd][e.ercAddress][0].balance += e.balance; + } else { + acc[e.compressedPkd][e.ercAddress].push({ balance: e.balance, tokenId: e.tokenId }); + } + return acc; + }, {}); + + return res; +} + // function to get the commitments for each ERC address of a pkd export async function getWalletCommitments() { const connection = await mongo.connection(MONGO_URL); diff --git a/nightfall-deployer/migrations/4_test_tokens_migration.js b/nightfall-deployer/migrations/4_test_tokens_migration.js index 96a09ac16..c1b056102 100644 --- a/nightfall-deployer/migrations/4_test_tokens_migration.js +++ b/nightfall-deployer/migrations/4_test_tokens_migration.js @@ -4,10 +4,12 @@ const ERC1155Mock = artifacts.require('ERC1155Mock.sol'); const recipientAddress = '0x9c8b2276d490141ae1440da660e470e7c0349c63'; const walletTestAddress = '0xfCb059A4dB5B961d3e48706fAC91a55Bad0035C9'; +const liquidityProviderAddress = '0x4789FD18D5d71982045d85d5218493fD69F55AC4'; +const nERC721 = 100; module.exports = function(deployer) { deployer.then(async () => { - await deployer.deploy(ERC20Mock, 100000000000); // initialSupply + await deployer.deploy(ERC20Mock, 1000000000000000); // initialSupply await deployer.deploy(ERC721Mock); await deployer.deploy(ERC1155Mock); @@ -15,14 +17,15 @@ module.exports = function(deployer) { const ERC721deployed = await ERC721Mock.deployed(); const ERC1155deployed = await ERC1155Mock.deployed(); // For e2e tests - await ERC721deployed.awardItem(recipientAddress, 'https://erc721mock/item-id-1.json'); - await ERC721deployed.awardItem(recipientAddress, 'https://erc721mock/item-id-2.json'); - await ERC721deployed.awardItem(recipientAddress, 'https://erc721mock/item-id-3.json'); + for (let i=0; i < nERC721; i++){ + await ERC721deployed.awardItem(recipientAddress, `https://erc721mock/item-id-${i}.json`); + } // For testing the wallet - await ERC20deployed.transfer(walletTestAddress, 1000000); - await ERC721deployed.awardItem(walletTestAddress, 'https://erc721mock/item-id-1.json'); - await ERC721deployed.awardItem(walletTestAddress, 'https://erc721mock/item-id-2.json'); - await ERC721deployed.awardItem(walletTestAddress, 'https://erc721mock/item-id-3.json'); + await ERC20deployed.transfer(walletTestAddress, 10000000000); + await ERC20deployed.transfer(liquidityProviderAddress, 1000000000000); + for (let i=0; i < 100; i++){ + await ERC721deployed.awardItem(walletTestAddress, `https://erc721mock/item-id-${i}.json`); + } await ERC1155deployed.safeBatchTransferFrom(recipientAddress, walletTestAddress, [0, 1, 4], [5000000, 200000, 100000], []); }); diff --git a/package.json b/package.json index d813c6f19..8b897a40b 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "test-chain-reorg": "env-cmd -e development mocha --timeout 0 --bail test/chain-reorg.mjs", "test-e2e": "env-cmd -e development mocha --timeout 0 --bail test/e2e/nightfall-sdk.test.mjs", "test-e2e-ropsten": "env-cmd -e ropsten mocha --timeout 0 --bail test/e2e/nightfall-sdk.test.mjs", + "test-ercmocks": "env-cmd -e development mocha --timeout 0 --bail test/e2e/ercmocks.test.mjs", "lint": "eslint . --ext js,mjs,jsx && find-unused-exports", "prepare": "husky install", "doc:build:sdk": "jsdoc -c jsdoc.json cli/lib/nf3.mjs" diff --git a/test/e2e/ercmocks.test.mjs b/test/e2e/ercmocks.test.mjs index 714b76f06..019c5afa8 100644 --- a/test/e2e/ercmocks.test.mjs +++ b/test/e2e/ercmocks.test.mjs @@ -2,6 +2,7 @@ import chai from 'chai'; import chaiHttp from 'chai-http'; import chaiAsPromised from 'chai-as-promised'; import Nf3 from '../../cli/lib/nf3.mjs'; +import { getERCInfo } from '../../cli/lib/tokens.mjs'; import { connectWeb3, closeWeb3Connection, @@ -88,6 +89,11 @@ describe('Testing the Nightfall ERCMocks', () => { it('should transfer some token of the ERC20 contract mock', async function () { const erc20Token = new web3.eth.Contract(nf3.contracts.ERC20, erc20Address); const amount = 3000; + const tokensInfo = await getERCInfo(erc20Address, nf3.ethereumAddress, web3, { + toEth: true, + details: true, + }); + console.log(`TOKENS INFO ${nf3.ethereumAddress} (${erc20Address}): `, tokensInfo); const balanceBefore = await erc20Token.methods.balanceOf(nf3.ethereumAddress).call(); const decimals = await erc20Token.methods.decimals().call(); expect(Number(decimals)).to.be.equal(9); @@ -130,6 +136,12 @@ describe('Testing the Nightfall ERCMocks', () => { ` Balance ERC721Mock after transfer tokenId ${tokenId} [${nf3.ethereumAddress}]: ${balanceAfter}`, ); expect(Number(balanceAfter)).to.be.equal(Number(balanceBefore) - 1); + const tokensInfo = await getERCInfo(erc721Address, nf3.ethereumAddress, web3, { + details: true, + }); + console.log(`TOKENS INFO ${nf3.ethereumAddress} (${erc721Address}): `, tokensInfo); + expect(Number(tokensInfo.balance)).to.be.equal(Number(balanceAfter)); + expect(Number(tokensInfo.details.length)).to.be.equal(Number(balanceAfter)); await nf3.setEthereumSigningKey(walletTestSigningkey); txDataToSign = await erc721Token.methods @@ -153,9 +165,17 @@ describe('Testing the Nightfall ERCMocks', () => { }); it('should get the balance of the ERC1155 contract mock', async function () { + const Id = 1; // Index Id from ERC1155 to check const erc1155Token = new web3.eth.Contract(nf3.contracts.ERC1155, erc1155Address); - const balance = await erc1155Token.methods.balanceOf(nf3.ethereumAddress, 1).call(); + const balance = await erc1155Token.methods.balanceOf(nf3.ethereumAddress, Id).call(); expect(Number(balance)).to.be.greaterThan(0); + const tokensInfo = await getERCInfo(erc1155Address, nf3.ethereumAddress, web3, { + details: true, + }); + console.log(`TOKENS INFO ${nf3.ethereumAddress} (${erc1155Address}): `, tokensInfo); + expect(Number(balance)).to.be.equal( + Number(tokensInfo.details.find(tokenId => tokenId.Id === Id.toString()).amount), + ); }); it('should get the balance of wallet address of the ERC1155 contract mock', async function () { diff --git a/wallet/craco.config.js b/wallet/craco.config.js new file mode 100644 index 000000000..ff75e1adb --- /dev/null +++ b/wallet/craco.config.js @@ -0,0 +1,4 @@ +/* eslint-disable global-require */ +module.exports = { + plugins: [{ plugin: require('@semantic-ui-react/craco-less') }], +}; diff --git a/wallet/package-lock.json b/wallet/package-lock.json index f8ea03e65..4d6b59081 100644 --- a/wallet/package-lock.json +++ b/wallet/package-lock.json @@ -1251,6 +1251,62 @@ "minimist": "^1.2.0" } }, + "@craco/craco": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@craco/craco/-/craco-6.4.2.tgz", + "integrity": "sha512-egIooyvuzKM5dsvWe/U5ISyFpZwLnG9uuTF1fU4s/6b/hE8MvoxyaxKymQKgbtpfOZeH0ebtEP4cbH7xZ4XRbw==", + "dev": true, + "requires": { + "cosmiconfig": "^7.0.1", + "cross-spawn": "^7.0.0", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "webpack-merge": "^4.2.2" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "@csstools/convert-colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", @@ -2231,6 +2287,14 @@ } } }, + "@semantic-ui-react/craco-less": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@semantic-ui-react/craco-less/-/craco-less-1.2.3.tgz", + "integrity": "sha512-EPE2YA0pTcObuGO3cRYXMybTUJ27tamEQrHk6BC8cAkP6CTuuYZiw6hFNjEIOQodOnIXhy/cJ5dVeyKNnliL0g==", + "requires": { + "craco-less": "^1.15.0" + } + }, "@semantic-ui-react/event-stack": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@semantic-ui-react/event-stack/-/event-stack-3.1.2.tgz", @@ -4831,6 +4895,14 @@ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==" }, + "copy-anything": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.3.tgz", + "integrity": "sha512-GK6QUtisv4fNS+XcI7shX0Gx9ORg7QqIznyfho79JTnX1XhLiyZHfftvGiziqzRiEi/Bjhgpi+D2o7HxJFPnDQ==", + "requires": { + "is-what": "^3.12.0" + } + }, "copy-concurrently": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", @@ -4911,6 +4983,15 @@ "yaml": "^1.10.0" } }, + "craco-less": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/craco-less/-/craco-less-1.20.0.tgz", + "integrity": "sha512-oP7kMRFOwwCPAlS+RBfA0yt9qAfSH8EOzJOQyzspVOECDtATTLXYyEYd0ghoybbReVRZbOmGxNtPWh4ALpVRng==", + "requires": { + "less": "^4.1.1", + "less-loader": "^7.3.0" + } + }, "crc-32": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", @@ -8245,6 +8326,12 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "optional": true + }, "immer": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz", @@ -8727,6 +8814,11 @@ "call-bind": "^1.0.0" } }, + "is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==" + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -10482,6 +10574,52 @@ "webpack-sources": "^1.1.0" } }, + "less": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/less/-/less-4.1.2.tgz", + "integrity": "sha512-EoQp/Et7OSOVu0aJknJOtlXZsnr8XE8KwuzTHOLeVSEx8pVWUICc8Q0VYRHgzyjX78nMEyC/oztWFbgyhtNfDA==", + "requires": { + "copy-anything": "^2.0.1", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^2.5.2", + "parse-node-version": "^1.0.1", + "source-map": "~0.6.0", + "tslib": "^2.3.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "less-loader": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-7.3.0.tgz", + "integrity": "sha512-Mi8915g7NMaLlgi77mgTTQvK022xKRQBIVDSyfl3ErTuBhmZBQab0mjeJjNNqGbdR+qrfTleKXqbGI4uEFavxg==", + "requires": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -11104,6 +11242,28 @@ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, + "needle": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz", + "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==", + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "optional": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -16731,6 +16891,11 @@ "lines-and-columns": "^1.1.6" } }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==" + }, "parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -19533,10 +19698,10 @@ "node-forge": "^0.10.0" } }, - "semantic-ui-css": { + "semantic-ui-less": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/semantic-ui-css/-/semantic-ui-css-2.4.1.tgz", - "integrity": "sha512-Pkp0p9oWOxlH0kODx7qFpIRYpK1T4WJOO4lNnpNPOoWKCrYsfHqYSKgk5fHfQtnWnsAKy7nLJMW02bgDWWFZFg==", + "resolved": "https://registry.npmjs.org/semantic-ui-less/-/semantic-ui-less-2.4.1.tgz", + "integrity": "sha512-/+nhPV6If2ydCz89/SSWzYD8ualDtjh4Tk3F6cqRj2luZj1DRjJ2nM9NKqmeyLlQFNFM94wpnpKXcjxRzZh5GA==", "requires": { "jquery": "x.*" } @@ -22874,6 +23039,15 @@ } } }, + "webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, "webpack-sources": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", diff --git a/wallet/package.json b/wallet/package.json index 632995d97..ca7b32360 100644 --- a/wallet/package.json +++ b/wallet/package.json @@ -4,6 +4,7 @@ "private": true, "main": "./src/index.jsx", "dependencies": { + "@semantic-ui-react/craco-less": "^1.2.3", "@testing-library/jest-dom": "^5.14.1", "bip39": "^3.0.4", "bootstrap": "^5.1.3", @@ -21,19 +22,19 @@ "redux": "4.1.1", "redux-logger": "^3.0.6", "redux-thunk": "^2.3.0", - "semantic-ui-css": "^2.4.1", + "semantic-ui-less": "^2.4.1", "semantic-ui-react": "^2.0.4", "web-vitals": "^2.1.0", "web3": "^1.6.0" }, "scripts": { - "start": "REACT_APP_ENVIRONMENT=Localhost react-scripts start", - "start:docker": "REACT_APP_ENVIRONMENT=Docker PORT=3010 react-scripts start", - "start:ropsten": "REACT_APP_ENVIRONMENT=Ropsten react-scripts start", - "build": "REACT_APP_ENVIRONMENT=Ropsten react-scripts build", + "start": "REACT_APP_ENVIRONMENT=Localhost craco start", + "start:docker": "REACT_APP_ENVIRONMENT=Docker PORT=3010 craco start", + "start:ropsten": "REACT_APP_ENVIRONMENT=Ropsten craco start", + "build": "REACT_APP_ENVIRONMENT=Ropsten craco build", "deploy": "npm run build && aws s3 sync build/ s3://nightfallv3-wallet --cache-control max-age=172800 --delete && aws configure set preview.cloudfront true && aws cloudfront create-invalidation --distribution-id E9K9C7N0TG7LG --paths \"/*\"", - "test": "react-scripts test --env=jsdom", - "eject": "react-scripts eject" + "test": "craco test --env=jsdom", + "eject": "craco eject" }, "browserslist": { "production": [ @@ -46,5 +47,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "@craco/craco": "^6.4.2" } } diff --git a/wallet/src/constants.js b/wallet/src/constants.js index fc6c8e1cd..fcc448a6f 100644 --- a/wallet/src/constants.js +++ b/wallet/src/constants.js @@ -22,7 +22,8 @@ const METAMASK_MESSAGE = const TRANSACTION_MAX_RETRIES = 10; const TRANSACTION_RETRY_PERIOD = 10000; // 10s -const BALANCE_INTERVAL = 30000; +// TODO - verify balance refres rate +const BALANCE_INTERVAL = 60000; export { DEFAULT_NF_ADDRESS_INDEX, diff --git a/wallet/src/images/polygon.svg b/wallet/src/images/polygon.svg new file mode 100644 index 000000000..797deb17e --- /dev/null +++ b/wallet/src/images/polygon.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/wallet/src/index.jsx b/wallet/src/index.jsx index bd0cb1641..12344a8de 100644 --- a/wallet/src/index.jsx +++ b/wallet/src/index.jsx @@ -6,7 +6,7 @@ import configureStore from './store'; import 'bootstrap/dist/css/bootstrap.min.css'; import 'font-awesome/css/font-awesome.min.css'; import 'bootstrap-social/bootstrap-social.css'; -import 'semantic-ui-css/semantic.min.css'; +import 'semantic-ui-less/semantic.less'; import './index.css'; import './views/app.style.css'; import App from './views/app.view.jsx'; diff --git a/wallet/src/semantic-ui/site/collections/breadcrumb.overrides b/wallet/src/semantic-ui/site/collections/breadcrumb.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/collections/breadcrumb.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/collections/breadcrumb.variables b/wallet/src/semantic-ui/site/collections/breadcrumb.variables new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/collections/breadcrumb.variables @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/collections/form.overrides b/wallet/src/semantic-ui/site/collections/form.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/collections/form.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/collections/form.variables b/wallet/src/semantic-ui/site/collections/form.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/collections/form.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/collections/grid.overrides b/wallet/src/semantic-ui/site/collections/grid.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/collections/grid.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/collections/grid.variables b/wallet/src/semantic-ui/site/collections/grid.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/collections/grid.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/collections/menu.overrides b/wallet/src/semantic-ui/site/collections/menu.overrides new file mode 100644 index 000000000..c172e5f52 --- /dev/null +++ b/wallet/src/semantic-ui/site/collections/menu.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ \ No newline at end of file diff --git a/wallet/src/semantic-ui/site/collections/menu.variables b/wallet/src/semantic-ui/site/collections/menu.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/collections/menu.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/collections/message.overrides b/wallet/src/semantic-ui/site/collections/message.overrides new file mode 100644 index 000000000..96091c36c --- /dev/null +++ b/wallet/src/semantic-ui/site/collections/message.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/collections/message.variables b/wallet/src/semantic-ui/site/collections/message.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/collections/message.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/collections/table.overrides b/wallet/src/semantic-ui/site/collections/table.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/collections/table.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/collections/table.variables b/wallet/src/semantic-ui/site/collections/table.variables new file mode 100644 index 000000000..64c93b19a --- /dev/null +++ b/wallet/src/semantic-ui/site/collections/table.variables @@ -0,0 +1,16 @@ +/******************************* + User Variable Overrides +*******************************/ +@backgroundColor: #c8c8fb; +@activeBgColor: #9e9ee6; +@headerBgColor: #6f56b1; +@backgroundImage: none; + + +@activeColor: @black; +/* @activeBackgroundColor: @activeBgColor; +@headerBackground: @headerBgColor; +@headerColor: @white; */ +@rowBorder: 4px solid @internalBorderColor; +@headerBorder: 4px solid @white; + diff --git a/wallet/src/semantic-ui/site/elements/button.overrides b/wallet/src/semantic-ui/site/elements/button.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/button.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/button.variables b/wallet/src/semantic-ui/site/elements/button.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/button.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/container.overrides b/wallet/src/semantic-ui/site/elements/container.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/container.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/container.variables b/wallet/src/semantic-ui/site/elements/container.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/container.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/divider.overrides b/wallet/src/semantic-ui/site/elements/divider.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/divider.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/divider.variables b/wallet/src/semantic-ui/site/elements/divider.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/divider.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/flag.overrides b/wallet/src/semantic-ui/site/elements/flag.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/flag.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/flag.variables b/wallet/src/semantic-ui/site/elements/flag.variables new file mode 100644 index 000000000..e3e125d6f --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/flag.variables @@ -0,0 +1,3 @@ +/*------------------- + Flag Variables +--------------------*/ diff --git a/wallet/src/semantic-ui/site/elements/header.overrides b/wallet/src/semantic-ui/site/elements/header.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/header.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/header.variables b/wallet/src/semantic-ui/site/elements/header.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/header.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/icon.overrides b/wallet/src/semantic-ui/site/elements/icon.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/icon.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/icon.variables b/wallet/src/semantic-ui/site/elements/icon.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/icon.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/image.overrides b/wallet/src/semantic-ui/site/elements/image.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/image.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/image.variables b/wallet/src/semantic-ui/site/elements/image.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/image.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/input.overrides b/wallet/src/semantic-ui/site/elements/input.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/input.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/input.variables b/wallet/src/semantic-ui/site/elements/input.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/input.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/label.overrides b/wallet/src/semantic-ui/site/elements/label.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/label.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/label.variables b/wallet/src/semantic-ui/site/elements/label.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/label.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/list.overrides b/wallet/src/semantic-ui/site/elements/list.overrides new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/list.overrides @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/list.variables b/wallet/src/semantic-ui/site/elements/list.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/list.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/loader.overrides b/wallet/src/semantic-ui/site/elements/loader.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/loader.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/loader.variables b/wallet/src/semantic-ui/site/elements/loader.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/loader.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/rail.overrides b/wallet/src/semantic-ui/site/elements/rail.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/rail.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/rail.variables b/wallet/src/semantic-ui/site/elements/rail.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/rail.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/reveal.overrides b/wallet/src/semantic-ui/site/elements/reveal.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/reveal.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/reveal.variables b/wallet/src/semantic-ui/site/elements/reveal.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/reveal.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/segment.overrides b/wallet/src/semantic-ui/site/elements/segment.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/segment.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/segment.variables b/wallet/src/semantic-ui/site/elements/segment.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/segment.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/step.overrides b/wallet/src/semantic-ui/site/elements/step.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/step.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/elements/step.variables b/wallet/src/semantic-ui/site/elements/step.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/elements/step.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/globals/reset.overrides b/wallet/src/semantic-ui/site/globals/reset.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/globals/reset.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/globals/reset.variables b/wallet/src/semantic-ui/site/globals/reset.variables new file mode 100644 index 000000000..cd9554465 --- /dev/null +++ b/wallet/src/semantic-ui/site/globals/reset.variables @@ -0,0 +1,3 @@ +/******************************* + User Global Variables +*******************************/ diff --git a/wallet/src/semantic-ui/site/globals/site.overrides b/wallet/src/semantic-ui/site/globals/site.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/globals/site.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/globals/site.variables b/wallet/src/semantic-ui/site/globals/site.variables new file mode 100644 index 000000000..5a630cbd4 --- /dev/null +++ b/wallet/src/semantic-ui/site/globals/site.variables @@ -0,0 +1,6 @@ +/******************************* + User Global Variables +*******************************/ +/*@primaryColor: #8248E5; +@pageBackground: #eff0f1;*/ +@primaryColor: #808080; diff --git a/wallet/src/semantic-ui/site/modules/accordion.overrides b/wallet/src/semantic-ui/site/modules/accordion.overrides new file mode 100644 index 000000000..660e664b5 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/accordion.overrides @@ -0,0 +1,3 @@ +/******************************* + User Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/accordion.variables b/wallet/src/semantic-ui/site/modules/accordion.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/accordion.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/chatroom.overrides b/wallet/src/semantic-ui/site/modules/chatroom.overrides new file mode 100644 index 000000000..660e664b5 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/chatroom.overrides @@ -0,0 +1,3 @@ +/******************************* + User Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/chatroom.variables b/wallet/src/semantic-ui/site/modules/chatroom.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/chatroom.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/checkbox.overrides b/wallet/src/semantic-ui/site/modules/checkbox.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/checkbox.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/checkbox.variables b/wallet/src/semantic-ui/site/modules/checkbox.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/checkbox.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/dimmer.overrides b/wallet/src/semantic-ui/site/modules/dimmer.overrides new file mode 100644 index 000000000..660e664b5 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/dimmer.overrides @@ -0,0 +1,3 @@ +/******************************* + User Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/dimmer.variables b/wallet/src/semantic-ui/site/modules/dimmer.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/dimmer.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/dropdown.overrides b/wallet/src/semantic-ui/site/modules/dropdown.overrides new file mode 100644 index 000000000..660e664b5 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/dropdown.overrides @@ -0,0 +1,3 @@ +/******************************* + User Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/dropdown.variables b/wallet/src/semantic-ui/site/modules/dropdown.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/dropdown.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/embed.overrides b/wallet/src/semantic-ui/site/modules/embed.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/embed.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/embed.variables b/wallet/src/semantic-ui/site/modules/embed.variables new file mode 100644 index 000000000..e69de29bb diff --git a/wallet/src/semantic-ui/site/modules/modal.overrides b/wallet/src/semantic-ui/site/modules/modal.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/modal.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/modal.variables b/wallet/src/semantic-ui/site/modules/modal.variables new file mode 100644 index 000000000..3b3946c1e --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/modal.variables @@ -0,0 +1,14 @@ +/******************************* + Site Overrides +*******************************/ +@backgroundColor: #c8c8fb; +@activeBgColor: #9e9ee6; +@headerBgColor: #6f56b1; +@backgroundImage: none; +/*@background: @backgroundColor @backgroundImage; + + +@activeColor: @black; +@activeBackgroundColor: @activeBgColor; +@headerBackground: @headerBgColor; +@headerColor: @white;*/ \ No newline at end of file diff --git a/wallet/src/semantic-ui/site/modules/nag.overrides b/wallet/src/semantic-ui/site/modules/nag.overrides new file mode 100644 index 000000000..660e664b5 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/nag.overrides @@ -0,0 +1,3 @@ +/******************************* + User Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/nag.variables b/wallet/src/semantic-ui/site/modules/nag.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/nag.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/popup.overrides b/wallet/src/semantic-ui/site/modules/popup.overrides new file mode 100644 index 000000000..660e664b5 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/popup.overrides @@ -0,0 +1,3 @@ +/******************************* + User Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/popup.variables b/wallet/src/semantic-ui/site/modules/popup.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/popup.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/progress.overrides b/wallet/src/semantic-ui/site/modules/progress.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/progress.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/progress.variables b/wallet/src/semantic-ui/site/modules/progress.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/progress.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/rating.overrides b/wallet/src/semantic-ui/site/modules/rating.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/rating.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/rating.variables b/wallet/src/semantic-ui/site/modules/rating.variables new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/rating.variables @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/search.overrides b/wallet/src/semantic-ui/site/modules/search.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/search.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/search.variables b/wallet/src/semantic-ui/site/modules/search.variables new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/search.variables @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/shape.overrides b/wallet/src/semantic-ui/site/modules/shape.overrides new file mode 100644 index 000000000..660e664b5 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/shape.overrides @@ -0,0 +1,3 @@ +/******************************* + User Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/shape.variables b/wallet/src/semantic-ui/site/modules/shape.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/shape.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/sidebar.overrides b/wallet/src/semantic-ui/site/modules/sidebar.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/sidebar.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/sidebar.variables b/wallet/src/semantic-ui/site/modules/sidebar.variables new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/sidebar.variables @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/sticky.overrides b/wallet/src/semantic-ui/site/modules/sticky.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/sticky.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/sticky.variables b/wallet/src/semantic-ui/site/modules/sticky.variables new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/sticky.variables @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/tab.overrides b/wallet/src/semantic-ui/site/modules/tab.overrides new file mode 100644 index 000000000..660e664b5 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/tab.overrides @@ -0,0 +1,3 @@ +/******************************* + User Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/tab.variables b/wallet/src/semantic-ui/site/modules/tab.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/tab.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/transition.overrides b/wallet/src/semantic-ui/site/modules/transition.overrides new file mode 100644 index 000000000..cba59efe6 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/transition.overrides @@ -0,0 +1,3 @@ +/******************************* + Site Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/modules/transition.variables b/wallet/src/semantic-ui/site/modules/transition.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/modules/transition.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/views/ad.overrides b/wallet/src/semantic-ui/site/views/ad.overrides new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/views/ad.overrides @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/views/ad.variables b/wallet/src/semantic-ui/site/views/ad.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/views/ad.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/views/card.overrides b/wallet/src/semantic-ui/site/views/card.overrides new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/views/card.overrides @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/views/card.variables b/wallet/src/semantic-ui/site/views/card.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/views/card.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/views/comment.overrides b/wallet/src/semantic-ui/site/views/comment.overrides new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/views/comment.overrides @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/views/comment.variables b/wallet/src/semantic-ui/site/views/comment.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/views/comment.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/views/feed.overrides b/wallet/src/semantic-ui/site/views/feed.overrides new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/views/feed.overrides @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/views/feed.variables b/wallet/src/semantic-ui/site/views/feed.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/views/feed.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/views/item.overrides b/wallet/src/semantic-ui/site/views/item.overrides new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/views/item.overrides @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/views/item.variables b/wallet/src/semantic-ui/site/views/item.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/views/item.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/views/statistic.overrides b/wallet/src/semantic-ui/site/views/statistic.overrides new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/views/statistic.overrides @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/site/views/statistic.variables b/wallet/src/semantic-ui/site/views/statistic.variables new file mode 100644 index 000000000..6f085f935 --- /dev/null +++ b/wallet/src/semantic-ui/site/views/statistic.variables @@ -0,0 +1,3 @@ +/******************************* + User Variable Overrides +*******************************/ diff --git a/wallet/src/semantic-ui/theme.config b/wallet/src/semantic-ui/theme.config new file mode 100644 index 000000000..7c15db393 --- /dev/null +++ b/wallet/src/semantic-ui/theme.config @@ -0,0 +1,94 @@ +/* + +████████╗██╗ ██╗███████╗███╗ ███╗███████╗███████╗ +╚══██╔══╝██║ ██║██╔════╝████╗ ████║██╔════╝██╔════╝ + ██║ ███████║█████╗ ██╔████╔██║█████╗ ███████╗ + ██║ ██╔══██║██╔══╝ ██║╚██╔╝██║██╔══╝ ╚════██║ + ██║ ██║ ██║███████╗██║ ╚═╝ ██║███████╗███████║ + ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚══════╝ + +*/ + +/******************************* + Theme Selection +*******************************/ + +/* To override a theme for an individual element + specify theme name below +*/ + +/* Global */ +@site : 'default'; +@reset : 'default'; + +/* Elements */ +@button : 'default'; +@container : 'default'; +@divider : 'default'; +@flag : 'default'; +@header : 'default'; +@icon : 'default'; +@image : 'default'; +@input : 'default'; +@label : 'default'; +@list : 'default'; +@loader : 'default'; +@placeholder : 'default'; +@rail : 'default'; +@reveal : 'default'; +@segment : 'default'; +@step : 'default'; + +/* Collections */ +@breadcrumb : 'default'; +@form : 'default'; +@grid : 'default'; +@menu : 'default'; +@message : 'default'; +@table : 'default'; + +/* Modules */ +@accordion : 'default'; +@checkbox : 'default'; +@dimmer : 'default'; +@dropdown : 'default'; +@embed : 'default'; +@modal : 'default'; +@nag : 'default'; +@popup : 'default'; +@progress : 'default'; +@rating : 'default'; +@search : 'default'; +@shape : 'default'; +@sidebar : 'default'; +@sticky : 'default'; +@tab : 'default'; +@transition : 'default'; + +/* Views */ +@ad : 'default'; +@card : 'default'; +@comment : 'default'; +@feed : 'default'; +@item : 'default'; +@statistic : 'default'; + +/******************************* + Folders +*******************************/ + +/* Path to theme packages */ +@themesFolder : 'themes'; + +/* Path to site override folder */ +@siteFolder : '../../src/semantic-ui/site'; + + +/******************************* + Import Theme +*******************************/ + +@import (multiple) '~semantic-ui-less/theme.less'; +@fontPath : '../../../themes/@{theme}/assets/fonts'; + +/* End Config */ diff --git a/wallet/src/store/token/token.actions.js b/wallet/src/store/token/token.actions.js index 070d02899..928294258 100644 --- a/wallet/src/store/token/token.actions.js +++ b/wallet/src/store/token/token.actions.js @@ -11,13 +11,23 @@ export function addToken( tokenAddress, tokenType, tokenId, + l2TokenId, tokenName, l1Balance, l2Balance, ) { return { type: tokenActionTypes.TOKEN_ADD, - payload: { compressedPkd, tokenAddress, tokenType, tokenId, tokenName, l1Balance, l2Balance }, + payload: { + compressedPkd, + tokenAddress, + tokenType, + tokenId, + l2TokenId, + tokenName, + l1Balance, + l2Balance, + }, }; } diff --git a/wallet/src/store/token/token.reducer.js b/wallet/src/store/token/token.reducer.js index 543ead3c0..bb2cb66d5 100644 --- a/wallet/src/store/token/token.reducer.js +++ b/wallet/src/store/token/token.reducer.js @@ -22,12 +22,12 @@ function tokenReducer(state = initialState, action) { tokenAddress: action.payload.tokenAddress, tokenType: action.payload.tokenType, tokenId: action.payload.tokenId, + l2TokenId: action.payload.l2TokenId, tokenName: action.payload.tokenName, tokenBalanceL1: action.payload.l1Balance, tokenBalanceL2: action.payload.l2Balance, }, ]; - Storage.tokensSet(action.payload.compressedPkd, newTokenPool); return { ...state, @@ -40,6 +40,7 @@ function tokenReducer(state = initialState, action) { tokenAddress: action.payload.tokenAddress, tokenType: action.payload.tokenType, tokenId: action.payload.tokenId, + l2TokenId: action.payload.l2TokenId, tokenName: action.payload.tokenName, tokenBalanceL1: action.payload.l1Balance, tokenBalanceL2: action.payload.l2Balance, diff --git a/wallet/src/store/token/token.thunks.js b/wallet/src/store/token/token.thunks.js index 09667a70e..69a75f164 100644 --- a/wallet/src/store/token/token.thunks.js +++ b/wallet/src/store/token/token.thunks.js @@ -16,7 +16,11 @@ const getTokens = tokens => { }; const mergeTokens = (tokens1, tokens2) => { - const tokenPool = [...tokens2]; + const tokenPool = [...tokens2].map(token => { + const obj = { ...token }; + obj.tokenBalanceL2 = '0'; + return obj; + }); for (const token1 of tokens1) { const duplicatedIndex = tokens2.findIndex( token2 => token2.tokenAddress === token1.tokenAddress, @@ -25,7 +29,6 @@ const mergeTokens = (tokens1, tokens2) => { tokenPool.push(token1); } else if (tokenPool[duplicatedIndex].tokenBalanceL2 !== token1.tokenBalanceL2) { tokenPool[duplicatedIndex].tokenBalanceL2 = token1.tokenBalanceL2; - tokenPool[duplicatedIndex].updated = true; } } return tokenPool; @@ -36,7 +39,6 @@ function tokensLoad(initTokens) { const { login: { nf3 }, } = getState(); - if (typeof nf3.ethereumAddress === 'undefined') return; const storedTokens = Storage.tokensGet(nf3.zkpKeys.compressedPkd); nf3 @@ -50,28 +52,42 @@ function tokensLoad(initTokens) { ...getTokens(storedTokens), ...getTokens(initTokens), ]); - if (tokenPool.length) { tokenPool.forEach(el => { // TODO: Pending retrieve tokenIds and token name Nf3.Tokens.getERCInfo(el.tokenAddress, nf3.ethereumAddress, nf3.web3, { toEth: true, tokenId: 0, + details: true, + tokenType: el.tokenType, }) - .then(l1Balance => { - if (el.tokenBalanceL1 !== l1Balance.balance || el.updated) { - dispatch( - tokenActions.addToken( - compressedPkd, - el.tokenAddress.toLowerCase(), - el.tokenType, - '0x00', - el.tokenName, - l1Balance.balance, - Nf3.Units.fromBaseUnit(el.tokenBalanceL2, l1Balance.decimals), - ), - ); - } + .then(tokenInfo => { + nf3 + .getLayer2BalancesDetails([el.tokenAddress]) + .then(tokenL2Details => { + let l2TokenId = null; + if (el.tokenBalanceL2 !== '0') { + l2TokenId = tokenL2Details[nf3.zkpKeys.compressedPkd][el.tokenAddress].map( + l2Token => l2Token.tokenId.toString(), + ); + } else { + l2TokenId = []; + } + const l1TokenId = tokenInfo.details.map(tokenDetails => tokenDetails.tokenId); + dispatch( + tokenActions.addToken( + compressedPkd, + el.tokenAddress.toLowerCase(), + el.tokenType, + l1TokenId, + l2TokenId, + el.tokenName, + tokenInfo.balance, + Nf3.Units.fromBaseUnit(el.tokenBalanceL2, tokenInfo.decimals), + ), + ); + }) + .catch(console.log); }) .catch(console.log()); }); diff --git a/wallet/src/store/transactions/transactions.thunks.js b/wallet/src/store/transactions/transactions.thunks.js index 5e0bddc2f..6c6d732d7 100644 --- a/wallet/src/store/transactions/transactions.thunks.js +++ b/wallet/src/store/transactions/transactions.thunks.js @@ -13,6 +13,9 @@ function txInstantWithdrawSubmit(withdrawTransactionHash, fee) { nf3 .requestInstantWithdrawal(withdrawTransactionHash, fee) .then(txReceipt => { + if (txReceipt === null) { + throw new Error('Non existent hash'); + } // TODO dispatch error dispatch(txActions.txSuccess(Nf3.Constants.TX_TYPES.INSTANT_WITHDRAW, txReceipt)); }) diff --git a/wallet/src/utils/tokens.js b/wallet/src/utils/tokens.js index 1fe5e6140..142652f2a 100644 --- a/wallet/src/utils/tokens.js +++ b/wallet/src/utils/tokens.js @@ -8,9 +8,10 @@ const tokens = [ tokenAddress: DEFAULT_TOKEN_ADDRESS.ERC20, tokenType: Nf3.Constants.TOKEN_TYPE.ERC20, tokenId: DEFAULT_TOKEN_ID.ERC20, + tokenIdL2: [], tokenName: 'TOKEN1', - tokenBalanceL1: '-', - tokenBalanceL2: '-', + tokenBalanceL1: '0', + tokenBalanceL2: '0', // decimals: 9, }, // DUMMY @@ -19,9 +20,10 @@ const tokens = [ tokenAddress: DEFAULT_TOKEN_ADDRESS.ERC721, tokenType: Nf3.Constants.TOKEN_TYPE.ERC721, tokenId: DEFAULT_TOKEN_ID.ERC721, + tokenIdL2: [], tokenName: 'TOKEN2', - tokenBalanceL1: '-', - tokenBalanceL2: '-', + tokenBalanceL1: '0', + tokenBalanceL2: '0', // decimals: 9, }, // DUMMY @@ -30,9 +32,10 @@ const tokens = [ tokenAddress: DEFAULT_TOKEN_ADDRESS.ERC1155, tokenType: Nf3.Constants.TOKEN_TYPE.ERC1155, tokenId: DEFAULT_TOKEN_ID.ERC1155, + tokenIdL2: [], tokenName: 'TOKEN3', - tokenBalanceL1: '-', - tokenBalanceL2: '-', + tokenBalanceL1: '0', + tokenBalanceL2: '0', // decimals: 9, }, ]; diff --git a/wallet/src/views/login/components/create-wallet.view.jsx b/wallet/src/views/login/components/create-wallet.view.jsx index f7b775820..686c2979a 100644 --- a/wallet/src/views/login/components/create-wallet.view.jsx +++ b/wallet/src/views/login/components/create-wallet.view.jsx @@ -39,7 +39,7 @@ function CreateWalletModal({ modalEnable, handleClickOnImport, toggleModalEnable return ( - Enter Nightfall Mnemonic + Enter Polygon Nightfall Mnemonic
@@ -55,12 +55,16 @@ function CreateWalletModal({ modalEnable, handleClickOnImport, toggleModalEnable -