add web3 and wallet contract actions:

This commit is contained in:
Andrea Franz 2019-11-29 17:43:00 +01:00
parent dc337a2ae5
commit 09158b15f4
No known key found for this signature in database
GPG Key ID: 4F0D2F2D9DE7F29D
7 changed files with 571 additions and 0 deletions

View File

@ -0,0 +1,81 @@
import { Dispatch } from 'redux';
import { RootState } from '../reducers';
import Web3 from 'web3';
import { abi as keycardWalletFactoryABI } from '../contracts/KeycardWalletFactory';
import { abi as keycardWalletABI } from '../contracts/KeycardWallet';
import { isEmptyAddress } from '../utils';
const walletFactoryAddress = "0xF42dC64c5F580FFC120d6bc281C1293E63d8132a";
const testKeycardAddress = "0xfD51b65f6Dee2aDd1C867c05d5B8d189b9da7060";
export const WALLET_FACTORY_LOADING = "WALLET_FACTORY_LOADING";
export interface WalletFactoryAction {
type: typeof WALLET_FACTORY_LOADING
keycardAddress: string
}
export const WALLET_KEYCARD_NOT_FOUND = "WALLET_KEYCARD_NOT_FOUND";
export interface WalletKeycardNotFoundAction {
type: typeof WALLET_KEYCARD_NOT_FOUND
keycardAddress: string
}
export const WALLET_LOADING = "WALLET_LOADING";
export interface WalletLoadingAction {
type: typeof WALLET_LOADING
address: string
}
export const WALLET_BALANCE_LOADED = "WALLET_BALANCE_LOADED";
export interface WalletBalanceLoadedAction {
type: typeof WALLET_BALANCE_LOADED
balance: string
}
export type WalletActions =
WalletFactoryAction |
WalletKeycardNotFoundAction |
WalletLoadingAction;
export const loadingWalletFactory = (keycardAddress: string): WalletFactoryAction => ({
type: WALLET_FACTORY_LOADING,
keycardAddress,
});
export const keycardNotFound = (keycardAddress: string): WalletKeycardNotFoundAction => ({
type: WALLET_KEYCARD_NOT_FOUND,
keycardAddress,
});
export const loadingWallet = (address: string): WalletLoadingAction => ({
type: WALLET_LOADING,
address,
});
export const balanceLoaded = (balance: string): WalletBalanceLoadedAction => ({
type: WALLET_BALANCE_LOADED,
balance,
});
export const loadWallet = (dispatch: Dispatch) => {
const keycardAddress = testKeycardAddress;
dispatch(loadingWalletFactory(keycardAddress));
const web3: Web3 = (window as any).web3;
const factory = new web3.eth.Contract(keycardWalletFactoryABI, walletFactoryAddress);
factory.methods.keycardsWallets(keycardAddress).call().then((walletAddress: string) => {
if (isEmptyAddress(walletAddress)) {
dispatch(keycardNotFound(keycardAddress));
return;
}
dispatch(loadingWallet(walletAddress));
const wallet = new web3.eth.Contract(keycardWalletABI, walletAddress);
return web3.eth.getBalance(walletAddress);
}).then((balance: string) => {
dispatch(balanceLoaded(balance));
}).catch((error: string) => {
//FIXME: manage error
console.log("error", error)
})
}

View File

@ -0,0 +1,69 @@
import Web3 from 'web3';
import {
Dispatch,
AnyAction,
} from 'redux';
import { RootState } from '../reducers';
import { loadWallet } from './wallet';
import { ThunkAction } from 'redux-thunk';
export const WEB3_INITIALIZED = "WEB3_INITIALIZED";
export interface Web3InitializedAction {
type: typeof WEB3_INITIALIZED
}
export const WEB3_ERROR = "WEB3_ERROR";
export interface Web3ErrorAction {
type: typeof WEB3_ERROR
error: string
}
export const WEB3_NETWORK_ID_LOADED = "WEB3_NETWORK_ID_LOADED";
export interface Web3NetworkIDLoadedAction {
type: typeof WEB3_NETWORK_ID_LOADED
networkID: number
}
export type Web3Actions =
Web3InitializedAction |
Web3ErrorAction |
Web3NetworkIDLoadedAction;
export const web3Initialized = (): Web3Actions => {
return {
type: WEB3_INITIALIZED,
};
}
export const web3NetworkIDLoaded = (id: number): Web3Actions => {
return {
type: WEB3_NETWORK_ID_LOADED,
networkID: id,
};
}
export const web3Error = (error: string): Web3Actions => {
return {
type: WEB3_ERROR,
error: error,
};
}
export const initializeWeb3 = () => {
//FIXME: move to config
const web3 = new Web3('https://ropsten.infura.io/v3/f315575765b14720b32382a61a89341a');
(window as any).web3 = web3;
return (dispatch: Dispatch, getState: () => RootState) => {
dispatch(web3Initialized());
web3.eth.net.getId().then((id) => {
dispatch(web3NetworkIDLoaded(id))
loadWallet(dispatch);
}).catch((err) => {
dispatch(web3Error(err))
})
}
}

View File

@ -0,0 +1,246 @@
import { AbiItem } from 'web3-utils';
export const abi: AbiItem[] = [
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"name": "",
"type": "bytes3"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "hash",
"type": "bytes32"
},
{
"name": "sig",
"type": "bytes"
}
],
"name": "recover",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "pure",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_keycard",
"type": "address"
}
],
"name": "setKeycard",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "withdraw",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "keycard",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_maxTxValue",
"type": "uint256"
}
],
"name": "setSettings",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "nonce",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_hashToSign",
"type": "bytes32"
},
{
"name": "_signature",
"type": "bytes"
},
{
"name": "_nonce",
"type": "uint256"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "requestPayment",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "settings",
"outputs": [
{
"name": "maxTxValue",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "pendingWithdrawals",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"name": "_name",
"type": "bytes3"
},
{
"name": "_keycard",
"type": "address"
},
{
"name": "_maxTxValue",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"payable": true,
"stateMutability": "payable",
"type": "fallback"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "nonce",
"type": "uint256"
},
{
"indexed": false,
"name": "to",
"type": "address"
},
{
"indexed": false,
"name": "value",
"type": "uint256"
}
],
"name": "NewPaymentRequest",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "to",
"type": "address"
},
{
"indexed": false,
"name": "value",
"type": "uint256"
}
],
"name": "NewWithdrawal",
"type": "event"
}
]

View File

@ -0,0 +1,104 @@
import { AbiItem } from 'web3-utils';
export const abi: AbiItem[] = [
{
"constant": false,
"inputs": [
{
"name": "name",
"type": "bytes3"
},
{
"name": "keycard",
"type": "address"
},
{
"name": "maxTxValue",
"type": "uint256"
}
],
"name": "create",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function",
},
{
"constant": true,
"inputs": [
{
"name": "owner",
"type": "address"
}
],
"name": "ownerWalletsCount",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "keycardsWallets",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
},
{
"name": "",
"type": "uint256"
}
],
"name": "ownersWallets",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function",
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "wallet",
"type": "address"
},
{
"indexed": false,
"name": "name",
"type": "bytes3"
}
],
"name": "NewWallet",
"type": "event",
}
]

View File

@ -8,6 +8,7 @@ import {
Middleware,
MiddlewareAPI,
Dispatch,
AnyAction,
} from 'redux'
import { initializeWeb3 } from './actions/web3';
import { createRootReducer } from './reducers'

View File

@ -0,0 +1,45 @@
import {
Web3Actions,
WEB3_INITIALIZED,
WEB3_ERROR,
WEB3_NETWORK_ID_LOADED,
} from '../actions/web3';
export interface Web3State {
initialized: boolean
networkID: number | undefined
error: string | undefined
}
const initialState = {
initialized: false,
networkID: undefined,
error: undefined,
};
export function web3Reducer(state: Web3State = initialState, action: Web3Actions): Web3State {
switch (action.type) {
case WEB3_INITIALIZED: {
return {
...state,
initialized: true,
}
}
case WEB3_ERROR: {
return {
...state,
error: action.error,
}
}
case WEB3_NETWORK_ID_LOADED: {
return {
...state,
networkID: action.networkID,
}
}
}
return state;
}

View File

@ -0,0 +1,25 @@
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"
},
"include": [
"src"
]
}