Skip to content

Commit

Permalink
Merge pull request #551 from EYBlockchain/ilyas/pkd-offchain-sync
Browse files Browse the repository at this point in the history
Offchain transfers + sync + stored pkd
  • Loading branch information
LijuJoseJJ authored Mar 9, 2022
2 parents a8fcf25 + 89329a1 commit 0422687
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 66 deletions.
2 changes: 1 addition & 1 deletion wallet/.env
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
SKIP_PREFLIGHT_CHECK=true
OPTIMIST_API_URL=https://vqxy02tr5e.execute-api.us-east-2.amazonaws.com/Dev
LOCAL_API_URL=http://localhost:8081
LOCAL_OPTIMIST=true
LOCAL_OPTIMIST=process.env.LOCAL_OPTIMIST
OPTIMIST_WS_URL=wss://af3ys26lpe.execute-api.us-east-2.amazonaws.com/dev
LOCAL_WS_URL=ws://localhost:8082
6 changes: 3 additions & 3 deletions wallet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@
"zokrates-js": "^1.0.39"
},
"scripts": {
"start": "REACT_APP_ENVIRONMENT=Localhost craco start",
"start": "LOCAL_OPTIMIST=true 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 \"/*\"",
"build": "LOCAL_OPTIMIST=false craco build",
"deploy": "npm run build && aws s3 sync build s3://pnf-dev-browser --cache-control max-age=172800 --delete && aws configure set preview.cloudfront true && aws cloudfront create-invalidation --distribution-id ENV3X13MLR5YT --paths \"/*\"",
"test": "craco test --env=jsdom",
"eject": "craco eject",
"e2e-test": "NETWORK_NAME=ganache-nightfall RPC_URL=http://localhost:8546 CHAIN_ID=1337 PRIVATE_KEY=0x4775af73d6dc84a0ae76f8726bda4b9ecf187c377229cb39e1afa7a18236a69e npx synpress run --env TRANSACTIONS_PER_BLOCK=2"
Expand Down
17 changes: 13 additions & 4 deletions wallet/src/components/BridgeComponent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ import approveImg from '../../assets/img/modalImages/adeposit_approve1.png';
import depositConfirmed from '../../assets/img/modalImages/adeposit_confirmed.png';
import successHand from '../../assets/img/modalImages/success-hand.png';
import transferCompletedImg from '../../assets/img/modalImages/tranferCompleted.png';
import { pkdGet } from '../../utils/lib/local-storage';
import { decompressKey } from '../../nightfall-browser/services/keys';

const gen = require('general-number');

const { generalise } = gen;

const BridgeComponent = (props: any) => {
const [state] = useState(() => props[Object.keys(props)[1].toString()].value);
Expand Down Expand Up @@ -76,20 +82,22 @@ const BridgeComponent = (props: any) => {
console.log('TokenAddress', ercAddress);
switch (txType) {
case 'deposit': {
const pkd = decompressKey(generalise(pkdGet(await Web3.getAccount())));
await approve(ercAddress, shieldContractAddress, 'ERC20', tokenAmountWei.toString());
const { rawTransaction } = await deposit(
{
ercAddress,
tokenId: 0,
value: tokenAmountWei,
pkd: state.zkpKeys.pkd,
pkd,
nsk: state.zkpKeys.nsk,
fee: 1,
tokenType: 'ERC20',
},
shieldContractAddress,
);
return submitTransaction(rawTransaction, shieldContractAddress, 1);
await submitTransaction(rawTransaction, shieldContractAddress, 1);
break;
}

case 'withdraw': {
Expand Down Expand Up @@ -123,14 +131,16 @@ const BridgeComponent = (props: any) => {
shieldContractAddress,
);
console.log('rawTransaction', rawTransaction);
return submitTransaction(rawTransaction, shieldContractAddress, 1);
await submitTransaction(rawTransaction, shieldContractAddress, 1);
break;
}
break;
}

default:
break;
}
handleCloseConfirmModal();
handleClose();
return true;
}
Expand Down Expand Up @@ -423,7 +433,6 @@ const BridgeComponent = (props: any) => {
type="button"
className={stylesModal.continueTrasferButton}
id="Bridge_modal_continueTransferButton"
// onClick={() => triggerTx()}
onClick={() => triggerTx()}
>
Send Transaction
Expand Down
8 changes: 5 additions & 3 deletions wallet/src/components/TokenItem/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import metamaskIcon from '../../assets/svg/metamask.svg';
import maticImg from '../../assets/img/polygon-chain.svg';
import { UserContext } from '../../hooks/User/index.jsx';
import transfer from '../../nightfall-browser/services/transfer';
import { getContractAddress, submitTransaction } from '../../common-files/utils/contract';
import { getContractAddress } from '../../common-files/utils/contract';

const symbols = {
matic,
Expand All @@ -36,8 +36,9 @@ export default function TokenItem({

async function sendTx() {
const { address: shieldContractAddress } = (await getContractAddress('Shield')).data;
const { rawTransaction } = await transfer(
await transfer(
{
offchain: true,
ercAddress: tokenAddress,
tokenId: 0,
recipientData: {
Expand All @@ -50,7 +51,8 @@ export default function TokenItem({
},
shieldContractAddress,
);
return submitTransaction(rawTransaction, shieldContractAddress, 1);
console.log('Transfer Complete');
setShowSendModal(false);
}
const tokenNameId = `TokenItem_tokenName${symbol}`;
const tokenBalanceId = `TokenItem_tokenBalance${symbol}`;
Expand Down
36 changes: 14 additions & 22 deletions wallet/src/hooks/User/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,6 @@ import { getMaxBlock } from '../../nightfall-browser/services/database';

const { eventWsUrl } = global.config;

// export const reducer = (state, action) => {
// switch (action.type) {
// case 'toggle_button':
// return {
// ...state,
// active: !state.active,
// };
// default:
// return state;
// }
// };

export const initialState = {
active: false,
zkpKeys: {
Expand Down Expand Up @@ -78,23 +66,24 @@ export const UserProvider = ({ children }) => {
// Connection opened
socket.addEventListener('open', async function () {
console.log(`Websocket is open`);
const lastBlock = (await getMaxBlock())?._id ?? -1;
console.log('LasBlock', lastBlock);
const lastBlock = (await getMaxBlock()) ?? -1;
console.log('LastBlock', lastBlock);
socket.send(JSON.stringify({ type: 'sync', lastBlock }));
});

// Listen for messages
socket.addEventListener('message', async function (event) {
console.log('Message from server ', JSON.parse(event.data));
const parsed = JSON.parse(event.data);
if (parsed.type === 'sync')
await Promise.all(
parsed.historicalData.map(e => {
return blockProposedEventHandler(e, state.zkpKeys.ivk, state.zkpKeys.nsk);
}),
);
else if (parsed.type === 'blockProposed')
await blockProposedEventHandler(parsed.data, state.zkpKeys.ivk, state.zkpKeys.nsk);
if (parsed.type === 'sync') {
parsed.historicalData
.sort((a, b) => a.blockNumberL2 - b.blockNumberL2)
.reduce(async (acc, curr) => {
console.log('State', state.zkpKeys.ivk);
await acc; // Acc is a promise so we await it before processing the next one;
return blockProposedEventHandler(curr, [state.zkpKeys.ivk], [state.zkpKeys.nsk]); // TODO Should be array
}, Promise.resolve());
} else if (parsed.type === 'blockProposed') await blockProposedEventHandler(parsed.data, state.zkpKeys.ivk, state.zkpKeys.nsk);
// TODO Rollback Handler
});
setState(previousState => {
Expand All @@ -111,6 +100,9 @@ export const UserProvider = ({ children }) => {
mnemonic,
`m/44'/60'/0'/${DEFAULT_NF_ADDRESS_INDEX.toString()}`,
);

// Save Pkd
Storage.pkdSet(await Web3.getAccount(), zkpKeys.compressedPkd);
setState(previousState => {
return {
...previousState,
Expand Down
5 changes: 2 additions & 3 deletions wallet/src/nightfall-browser/event-handlers/block-proposed.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
// import getProposeBlockCalldata from '../services/process-calldata';
import Secrets from '../classes/secrets';
// import { ivks, nsks } from '../services/keys';
import { getLatestTree, saveTree, saveTransaction, saveBlock } from '../services/database';
import { getTreeByBlockNumberL2, saveTree, saveTransaction, saveBlock } from '../services/database';

const { ZERO } = global.config;

Expand All @@ -26,14 +26,13 @@ async function blockProposedEventHandler(data, ivks, nsks) {
const { blockNumber: currentBlockCount, transactionHash: transactionHashL1 } = data;
// const { transactions, block } = await getProposeBlockCalldata(data);
const { transactions, block } = data;
const latestTree = await getLatestTree();
const latestTree = await getTreeByBlockNumberL2(block.blockNumberL2 - 1);
const blockCommitments = transactions.map(t => t.commitments.filter(c => c !== ZERO)).flat();

if ((await countTransactionHashes(block.transactionHashes)) > 0) {
await saveBlock({ blockNumber: currentBlockCount, transactionHashL1, ...block });
await Promise.all(transactions.map(t => saveTransaction({ transactionHashL1, ...t })));
}

const dbUpdates = transactions.map(async transaction => {
// filter out non zero commitments and nullifiers
const nonZeroCommitments = transaction.commitments.flat().filter(n => n !== ZERO);
Expand Down
9 changes: 5 additions & 4 deletions wallet/src/nightfall-browser/services/commitment-storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,14 +279,13 @@ export async function markNullifiedOnChain(
if (filtered.length > 0) {
return Promise.all(
filtered.map(f => {
// const { isNullifiedOnChain: a, blockNumber: b } = f;
return db.put(
COMMITMENTS_COLLECTION,
{
...f,
isNullifiedOnChain: Number(blockNumberL2),
blockNumber,
transactionHashNullifiedL1,
...f,
},
f._id,
);
Expand All @@ -297,11 +296,13 @@ export async function markNullifiedOnChain(
}

// function to get the balance of commitments for each ERC address
export async function getWalletBalance() {
export async function getWalletBalance(pkd) {
const db = await connectDB();
const vals = await db.getAll(COMMITMENTS_COLLECTION);
const wallet =
Object.keys(vals).length > 0 ? vals.filter(v => !v.isNullified && v.isOnChain >= 0) : [];
Object.keys(vals).length > 0
? vals.filter(v => !v.isNullified && v.isOnChain >= 0 && v.preimage.compressedPkd === pkd)
: [];
// 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
Expand Down
26 changes: 16 additions & 10 deletions wallet/src/nightfall-browser/services/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export async function saveTree(blockNumber, blockNumberL2, timber) {
leafCount: timber.leafCount,
root: timber.root,
},
blockNumber,
blockNumberL2,
);
}

Expand All @@ -69,17 +69,20 @@ export async function getTreeByRoot(treeRoot) {

export async function getTreeByBlockNumberL2(blockNumberL2) {
const db = await connectDB();
const vals = await db.getAll(TIMBER_COLLECTION);
const { root, frontier, leafCount } = vals.filter(v => v.blockNumberL2 === blockNumberL2);
const t = new Timber(root, frontier, leafCount);
return t;
if (blockNumberL2 < 0) return new Timber(0, [], 0);
try {
const { root, frontier, leafCount } = await db.get(TIMBER_COLLECTION, blockNumberL2);
const t = new Timber(root, frontier, leafCount);
return t;
} catch (error) {
throw Error('Tree not Found');
// TODO Should handle this throw
}
}

export async function deleteTreeByBlockNumberL2(blockNumberL2) {
const db = await connectDB();
const vals = await db.getAll(TIMBER_COLLECTION);
const [match] = vals.filter(v => v.blockNumberL2 === blockNumberL2);
return db.delete(TIMBER_COLLECTION, match);
return db.delete(TIMBER_COLLECTION, blockNumberL2);
}

/**
Expand Down Expand Up @@ -146,9 +149,12 @@ export async function getBlockByTransactionHash(transactionHash) {

export async function getMaxBlock() {
const db = await connectDB();
const keys = await db.getAllKeys(SUBMITTED_BLOCKS_COLLECTION);
const timbers = await db.getAll(TIMBER_COLLECTION);
if (timbers.length === 0) return -1;
const keys = timbers.map(t => t.blockNumberL2);
const maxKey = Math.max(...keys);
return db.get(SUBMITTED_BLOCKS_COLLECTION, maxKey);
return maxKey;
// return db.get(SUBMITTED_BLOCKS_COLLECTION, maxKey);
}

/**
Expand Down
1 change: 1 addition & 0 deletions wallet/src/nightfall-browser/services/withdraw.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ async function withdraw(withdrawParams, shieldContractAddress) {
const th = optimisticWithdrawTransaction.transactionHash;
delete optimisticWithdrawTransaction.transactionHash;
optimisticWithdrawTransaction.transactionHash = th;
await markNullified(oldCommitment, optimisticWithdrawTransaction);
await saveTransaction(optimisticWithdrawTransaction);
return { transaction: optimisticWithdrawTransaction };
}
Expand Down
10 changes: 9 additions & 1 deletion wallet/src/utils/lib/local-storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,12 @@ function clear() {
storage.clear();
}

export { mnemonicGet, mnemonicSet, mnemonicRemove, tokensSet, tokensGet, clear };
function pkdSet(userKey, pkd) {
storage.setItem(`${userKey}/pkd`, pkd);
}

function pkdGet(userKey) {
return storage.getItem(`${userKey}/pkd`);
}

export { mnemonicGet, mnemonicSet, mnemonicRemove, tokensSet, tokensGet, clear, pkdGet, pkdSet };
3 changes: 2 additions & 1 deletion wallet/src/views/wallet/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ export default function Wallet() {
}, [state.mnemonic]);

useEffect(async () => {
const l2Balance = await getWalletBalance();
const pkd = Storage.pkdGet(await Web3.getAccount());
const l2Balance = await getWalletBalance(pkd);
const { address: newTokenAddress } = (await getContractAddress('ERC20Mock')).data; // TODO This is just until we get a list from Polygon
const updatedTokenState = initialTokenState.map(i => {
const { tokenAddress, ...rest } = i;
Expand Down
Loading

0 comments on commit 0422687

Please sign in to comment.