update pos app to work with the new tx type
This commit is contained in:
parent
244624c207
commit
996002ba0b
|
@ -2,6 +2,8 @@ import EmbarkJS from 'Embark/EmbarkJS';
|
||||||
import KeycardWalletFactory from 'Embark/contracts/KeycardWalletFactory';
|
import KeycardWalletFactory from 'Embark/contracts/KeycardWalletFactory';
|
||||||
import KeycardWallet from 'Embark/contracts/KeycardWallet';
|
import KeycardWallet from 'Embark/contracts/KeycardWallet';
|
||||||
import { emptyAddress } from '../utils';
|
import { emptyAddress } from '../utils';
|
||||||
|
import { recoverTypedSignature } from 'eth-sig-util';
|
||||||
|
import ethUtil from 'ethereumjs-util';
|
||||||
|
|
||||||
export const NEW_WALLET = 'NEW_WALLET';
|
export const NEW_WALLET = 'NEW_WALLET';
|
||||||
export const newWallet = () => ({
|
export const newWallet = () => ({
|
||||||
|
@ -64,9 +66,8 @@ export const loadingWallet = () => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
export const WALLET_LOADED = 'WALLET_LOADED';
|
export const WALLET_LOADED = 'WALLET_LOADED';
|
||||||
export const walletLoaded = (nonce, balance, maxTxValue) => ({
|
export const walletLoaded = (balance, maxTxValue) => ({
|
||||||
type: WALLET_LOADED,
|
type: WALLET_LOADED,
|
||||||
nonce,
|
|
||||||
balance,
|
balance,
|
||||||
maxTxValue,
|
maxTxValue,
|
||||||
});
|
});
|
||||||
|
@ -87,7 +88,9 @@ export const loadNetworkID = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function signPaymentRequest(message, cb) {
|
function signPaymentRequest(getState, message, cb) {
|
||||||
|
const state = getState();
|
||||||
|
|
||||||
let domain = [
|
let domain = [
|
||||||
{ name: "name", type: "string" },
|
{ name: "name", type: "string" },
|
||||||
{ name: "version", type: "string" },
|
{ name: "version", type: "string" },
|
||||||
|
@ -105,11 +108,11 @@ function signPaymentRequest(message, cb) {
|
||||||
let domainData = {
|
let domainData = {
|
||||||
name: "KeycardWallet",
|
name: "KeycardWallet",
|
||||||
version: "1",
|
version: "1",
|
||||||
chainId: 1,
|
chainId: state.networkID,
|
||||||
verifyingContract: KeycardWalletFactory.address
|
verifyingContract: KeycardWalletFactory.address
|
||||||
};
|
};
|
||||||
|
|
||||||
let data = {
|
const data = {
|
||||||
types: {
|
types: {
|
||||||
EIP712Domain: domain,
|
EIP712Domain: domain,
|
||||||
Payment: payment
|
Payment: payment
|
||||||
|
@ -119,13 +122,20 @@ function signPaymentRequest(message, cb) {
|
||||||
message: message
|
message: message
|
||||||
};
|
};
|
||||||
|
|
||||||
signer = web3.eth.defaultAccount;
|
const dataString = JSON.stringify(data);
|
||||||
|
|
||||||
if (web3.keycard.signTypedData) {
|
const signer = state.owner;
|
||||||
web3.keycard.signTypedData(data, cb);
|
if (window.ethereum && window.ethereum.isStatus) {
|
||||||
|
//FIXME: why is signer needed?
|
||||||
|
window.ethereum.send("keycard_signTypedData", [signer, dataString])
|
||||||
|
.then(resp => cb(undefined, resp, data))
|
||||||
|
.catch(err => cb(err, undefined, data));
|
||||||
} else {
|
} else {
|
||||||
let signer = web3.eth.defaultAccount
|
web3.currentProvider.sendAsync({
|
||||||
web3.currentProvider.sendAsync({method: "eth_signTypedData", params: [signer, data], from: signer}, cb);
|
method: "eth_signTypedData_v3",
|
||||||
|
params: [signer, dataString],
|
||||||
|
from: signer
|
||||||
|
}, (err, resp) => cb(err, resp, data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +211,6 @@ export const paymentRequested = () => ({
|
||||||
|
|
||||||
export const sendPaymentRequest = (walletContract, message, sig) => {
|
export const sendPaymentRequest = (walletContract, message, sig) => {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dispatch(requestingPayment())
|
dispatch(requestingPayment())
|
||||||
const requestPayment = await walletContract.methods.requestPayment(message, sig);
|
const requestPayment = await walletContract.methods.requestPayment(message, sig);
|
||||||
|
@ -211,7 +220,7 @@ export const sendPaymentRequest = (walletContract, message, sig) => {
|
||||||
});
|
});
|
||||||
dispatch(paymentRequested())
|
dispatch(paymentRequested())
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
alert(err)
|
console.error("ERROR: ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,15 +236,10 @@ export const loadWallet = (walletAddress, message, sig) => {
|
||||||
});
|
});
|
||||||
walletContract.address = walletAddress;
|
walletContract.address = walletAddress;
|
||||||
|
|
||||||
const balance = await web3.eth.getBalance(walletAddress);
|
const balance = await walletContract.methods.availableBalance().call();
|
||||||
const maxTxValue = await walletContract.methods.settings().call();
|
const settings = await walletContract.methods.settings().call();
|
||||||
|
|
||||||
let icon = "";
|
dispatch(walletLoaded(balance, settings.maxTxValue))
|
||||||
try {
|
|
||||||
icon = String.fromCodePoint(name);
|
|
||||||
} catch(e){}
|
|
||||||
|
|
||||||
dispatch(walletLoaded(nonce, balance, maxTxValue))
|
|
||||||
dispatch(sendPaymentRequest(walletContract, message, sig))
|
dispatch(sendPaymentRequest(walletContract, message, sig))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -268,6 +272,7 @@ export const findWallet = (keycardAddress, message, sig) => {
|
||||||
dispatch(findingWallet());
|
dispatch(findingWallet());
|
||||||
KeycardWalletFactory.methods.keycardsWallets(keycardAddress).call()
|
KeycardWalletFactory.methods.keycardsWallets(keycardAddress).call()
|
||||||
.then((address) => {
|
.then((address) => {
|
||||||
|
//FIXME: if 0x00, the wallet was not found
|
||||||
dispatch(walletFound(address))
|
dispatch(walletFound(address))
|
||||||
dispatch(loadWallet(address, message, sig))
|
dispatch(loadWallet(address, message, sig))
|
||||||
})
|
})
|
||||||
|
@ -277,14 +282,26 @@ export const findWallet = (keycardAddress, message, sig) => {
|
||||||
|
|
||||||
export const requestPayment = () => {
|
export const requestPayment = () => {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
|
const state = getState();
|
||||||
let block = await web3.eth.getBlock("latest");
|
let block = await web3.eth.getBlock("latest");
|
||||||
const message = {blockNumber: block.number, blockHash: block.hash, to: getState().owner, amount: getState().txAmount}
|
const message = {
|
||||||
|
blockNumber: block.number,
|
||||||
|
blockHash: block.hash,
|
||||||
|
to: state.owner,
|
||||||
|
amount: state.txAmount,
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
signPaymentRequest(message, function(err, sig) {
|
signPaymentRequest(getState, message, function(err, response, data) {
|
||||||
if (err) {
|
if (err) {
|
||||||
dispatch(web3Error(err))
|
dispatch(web3Error(err))
|
||||||
} else {
|
} else {
|
||||||
const address = web3.eth.accounts.recover(sig)
|
const sig = response.result;
|
||||||
|
const address = recoverTypedSignature({
|
||||||
|
data: data,
|
||||||
|
sig: sig,
|
||||||
|
})
|
||||||
|
|
||||||
dispatch(keycardDiscovered(address));
|
dispatch(keycardDiscovered(address));
|
||||||
dispatch(findWallet(address, message, sig));
|
dispatch(findWallet(address, message, sig));
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ export const compressedAddress = (a, padding) => {
|
||||||
|
|
||||||
const formattedBalance = (balance) => {
|
const formattedBalance = (balance) => {
|
||||||
if (balance) {
|
if (balance) {
|
||||||
return web3.utils.fromWei(balance);
|
return web3.utils.fromWei(new web3.utils.BN(balance));
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
|
@ -63,7 +63,6 @@ const Pos = ({requestingPayment, paymentRequested, onTapRequest, customerKeycard
|
||||||
|
|
||||||
{customerWallet && <p>
|
{customerWallet && <p>
|
||||||
<strong>Wallet</strong><br />
|
<strong>Wallet</strong><br />
|
||||||
Nonce: {customerWallet.nonce} <br />
|
|
||||||
Balance: {formattedBalance(customerWallet.balance)} <br />
|
Balance: {formattedBalance(customerWallet.balance)} <br />
|
||||||
Max Tx Value: {formattedBalance(customerWallet.maxTxValue)} <br />
|
Max Tx Value: {formattedBalance(customerWallet.maxTxValue)} <br />
|
||||||
</p>}
|
</p>}
|
||||||
|
|
|
@ -50,14 +50,13 @@ export default function(state, action) {
|
||||||
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ETHEREUM_LOAD_ERROR:
|
case ETHEREUM_LOAD_ERROR:
|
||||||
alert(action.error)
|
console.error(action.error)
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
loadingWeb3: false,
|
loadingWeb3: false,
|
||||||
loadingWeb3Error: action.err
|
loadingWeb3Error: action.err
|
||||||
});
|
});
|
||||||
case WEB3_ERROR:
|
case WEB3_ERROR:
|
||||||
console.error(action.error)
|
console.error(action.error)
|
||||||
alert(action.error)
|
|
||||||
break;
|
break;
|
||||||
case ETHEREUM_LOADED:
|
case ETHEREUM_LOADED:
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
|
@ -105,7 +104,6 @@ export default function(state, action) {
|
||||||
});
|
});
|
||||||
case WALLET_LOADED:
|
case WALLET_LOADED:
|
||||||
const wallet = {
|
const wallet = {
|
||||||
nonce: action.nonce,
|
|
||||||
balance: action.balance,
|
balance: action.balance,
|
||||||
maxTxValue: action.maxTxValue,
|
maxTxValue: action.maxTxValue,
|
||||||
}
|
}
|
||||||
|
@ -129,7 +127,7 @@ export default function(state, action) {
|
||||||
case PAYMENT_AMOUNT_VALUE_CHANGE:
|
case PAYMENT_AMOUNT_VALUE_CHANGE:
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
txAmount: action.value
|
txAmount: action.value
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
../../network-contracts/contracts
|
../../network-contracts/contracts
|
|
@ -9,7 +9,10 @@ contract KeycardWallet {
|
||||||
event NewWithdrawal(address to, uint256 value);
|
event NewWithdrawal(address to, uint256 value);
|
||||||
|
|
||||||
//TODO: replace with chainid opcode
|
//TODO: replace with chainid opcode
|
||||||
uint256 constant chainId = 1;
|
// uint256 constant chainId = 1;
|
||||||
|
uint256 constant chainId = 3;
|
||||||
|
// uint256 constant chainId = 5;
|
||||||
|
// uint256 constant chainId = 1337;
|
||||||
|
|
||||||
// must be less than 256, because the hash of older blocks cannot be retrieved
|
// must be less than 256, because the hash of older blocks cannot be retrieved
|
||||||
uint256 constant maxTxDelayInBlocks = 10;
|
uint256 constant maxTxDelayInBlocks = 10;
|
||||||
|
@ -177,6 +180,10 @@ contract KeycardWallet {
|
||||||
emit NewPaymentRequest(_payment.blockNumber, _payment.to, _payment.amount);
|
emit NewPaymentRequest(_payment.blockNumber, _payment.to, _payment.amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function availableBalance() public returns (int256) {
|
||||||
|
return int256(address(this).balance - totalPendingWithdrawals);
|
||||||
|
}
|
||||||
|
|
||||||
function withdraw() public {
|
function withdraw() public {
|
||||||
uint256 amount = pendingWithdrawals[msg.sender];
|
uint256 amount = pendingWithdrawals[msg.sender];
|
||||||
require(amount > 0, "no pending withdrawal");
|
require(amount > 0, "no pending withdrawal");
|
||||||
|
|
|
@ -63,8 +63,8 @@ contract KeycardWalletFactory is KeycardRegistry {
|
||||||
delete keycardsWallets[_keycard];
|
delete keycardsWallets[_keycard];
|
||||||
}
|
}
|
||||||
|
|
||||||
function countWalletsForOwner() public view returns (uint) {
|
function countWalletsForOwner(address owner) public view returns (uint) {
|
||||||
return ownersWallets[msg.sender].length;
|
return ownersWallets[owner].length;
|
||||||
}
|
}
|
||||||
|
|
||||||
function unregister(address _owner, address _keycard) public {
|
function unregister(address _owner, address _keycard) public {
|
||||||
|
|
|
@ -34,6 +34,7 @@ contract('KeycardWalletFactory', () => {
|
||||||
|
|
||||||
it ('create (keycard is owner)', async () => {
|
it ('create (keycard is owner)', async () => {
|
||||||
const keycard = "0x0000000000000000000000000000000000000002";
|
const keycard = "0x0000000000000000000000000000000000000002";
|
||||||
|
assert.equal(await KeycardWalletFactory.methods.countWalletsForOwner(keycard).call(), 0);
|
||||||
|
|
||||||
const create = KeycardWalletFactory.methods.create(keycard, {maxTxValue: 999, minBlockDistance: 1}, true);
|
const create = KeycardWalletFactory.methods.create(keycard, {maxTxValue: 999, minBlockDistance: 1}, true);
|
||||||
const receipt = await create.send({
|
const receipt = await create.send({
|
||||||
|
@ -44,6 +45,7 @@ contract('KeycardWalletFactory', () => {
|
||||||
const walletAddress = event.returnValues.wallet;
|
const walletAddress = event.returnValues.wallet;
|
||||||
assert.notEqual(walletAddress, keycard);
|
assert.notEqual(walletAddress, keycard);
|
||||||
|
|
||||||
|
assert.equal(await KeycardWalletFactory.methods.countWalletsForOwner(keycard).call(), 1);
|
||||||
assert.equal(await KeycardWalletFactory.methods.ownersWallets(keycard, 0).call(), walletAddress);
|
assert.equal(await KeycardWalletFactory.methods.ownersWallets(keycard, 0).call(), walletAddress);
|
||||||
assert.equal(await KeycardWalletFactory.methods.keycardsWallets(keycard).call(), walletAddress);
|
assert.equal(await KeycardWalletFactory.methods.keycardsWallets(keycard).call(), walletAddress);
|
||||||
});
|
});
|
||||||
|
@ -56,21 +58,23 @@ contract('KeycardWalletFactory', () => {
|
||||||
const receipt = await create.send({
|
const receipt = await create.send({
|
||||||
from: owner2
|
from: owner2
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.fail("should have failed")
|
assert.fail("should have failed")
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
assert.equal(getErrorReason(err), "the keycard is already associated to a wallet");
|
assert.equal(getErrorReason(err), "the keycard is already associated to a wallet");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it ('unregisterFromOwner', async () => {
|
it ('unregisterFromOwner', async () => {
|
||||||
|
assert.equal(await KeycardWalletFactory.methods.countWalletsForOwner(owner).call(), 1);
|
||||||
|
|
||||||
const walletAddress = await KeycardWalletFactory.methods.ownersWallets(owner, 0).call();
|
const walletAddress = await KeycardWalletFactory.methods.ownersWallets(owner, 0).call();
|
||||||
const unregisterFromOwner = KeycardWalletFactory.methods.unregisterFromOwner(walletAddress, "0x0000000000000000000000000000000000000001");
|
const unregisterFromOwner = KeycardWalletFactory.methods.unregisterFromOwner(walletAddress, "0x0000000000000000000000000000000000000001");
|
||||||
const receipt = await unregisterFromOwner.send({
|
const receipt = await unregisterFromOwner.send({
|
||||||
from: owner
|
from: owner
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.equal(await KeycardWalletFactory.methods.countWalletsForOwner().call(), 0);
|
assert.equal(await KeycardWalletFactory.methods.countWalletsForOwner(owner).call(), 0);
|
||||||
assert.equal(await KeycardWalletFactory.methods.keycardsWallets("0x0000000000000000000000000000000000000001").call(), "0x0000000000000000000000000000000000000000");
|
assert.equal(await KeycardWalletFactory.methods.keycardsWallets("0x0000000000000000000000000000000000000001").call(), "0x0000000000000000000000000000000000000000");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue