Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Developer UI: Send transaction from an app #133

Merged
merged 128 commits into from
Apr 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
128 commits
Select commit Hold shift + click to select a range
97edeb8
signer wip
mmv08 Feb 10, 2021
4d3a267
signer wip
mmv08 Feb 10, 2021
049b696
signer wip
mmv08 Feb 10, 2021
a17b80f
wip
mmv08 Feb 11, 2021
267341e
da mvp
mmv08 Feb 11, 2021
fdcd83c
dep bump
mmv08 Feb 12, 2021
10b15ef
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Feb 15, 2021
64a64f8
Signer wip
mmv08 Feb 15, 2021
80cd04d
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Feb 16, 2021
893b792
ethers signer
mmv08 Feb 16, 2021
231b769
remove yalc from signer
mmv08 Feb 16, 2021
58ae5d8
remove console.logs
mmv08 Feb 16, 2021
01510e3
change ethersprovider version
mmv08 Feb 16, 2021
7bc2323
add docs
mmv08 Feb 16, 2021
fc28d95
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Feb 17, 2021
a804dde
type fixes
mmv08 Feb 17, 2021
f4f3fcd
utils/poll: remove double increment
mmv08 Feb 17, 2021
8fe85e2
dep updatE
mmv08 Feb 17, 2021
d46985f
doc fix
mmv08 Feb 17, 2021
6fce81b
remove jsonrpc error check logic in checkError
mmv08 Feb 17, 2021
ef5fd35
ui: hello world
mmv08 Feb 25, 2021
22033b4
safe dev ui: hello world
mmv08 Feb 25, 2021
4b0fea4
pin jest version to the one required by react-scripts
mmv08 Feb 25, 2021
d382f58
test script fix
mmv08 Feb 25, 2021
ca851ac
dep bump
mmv08 Mar 1, 2021
a327276
use jest 26.6.0
mmv08 Mar 1, 2021
c223968
bootstrapping
mmv08 Mar 1, 2021
787cb46
wip
mmv08 Mar 1, 2021
a010adb
wip
mmv08 Mar 1, 2021
bafe43f
wip
mmv08 Mar 2, 2021
d8728b1
dep bump
mmv08 Mar 3, 2021
bb7b222
wip
mmv08 Mar 3, 2021
0b6fa02
trying to make header work
mmv08 Mar 3, 2021
9399b91
got this thing to render
mmv08 Mar 4, 2021
9e679a3
logo alignment
mmv08 Mar 4, 2021
ea25d98
a battle with changing default font family in mui
mmv08 Mar 4, 2021
b7b7a31
a battle with font scaling
mmv08 Mar 4, 2021
61c4a55
header
mmv08 Mar 5, 2021
b2232d8
header battle continues
mmv08 Mar 5, 2021
ef3ee32
material ui warning fixes
mmv08 Mar 9, 2021
5667c70
Fix web3modal
mmv08 Mar 9, 2021
b3f81cf
provider store wip
mmv08 Mar 9, 2021
e51e18f
provider store wip
mmv08 Mar 9, 2021
87b531d
provider details wip
mmv08 Mar 9, 2021
3e3cd42
provider details wip
mmv08 Mar 9, 2021
884dc57
Merge branch 'feature/dev-ui' of github.com:gnosis/safe-apps-sdk into…
mmv08 Mar 9, 2021
b8b1fd9
wip:
mmv08 Mar 10, 2021
3368b3c
connected account details
mmv08 Mar 10, 2021
59bd4f9
connect/disconnect provider
mmv08 Mar 10, 2021
b5839db
welcome page layout
mmv08 Mar 11, 2021
9fbf9f3
welcome page layout
mmv08 Mar 11, 2021
cd043af
welcome page layout wip
mmv08 Mar 12, 2021
16c0bfe
welcome page layout done
mmv08 Mar 12, 2021
f0f86b1
welcome page connect provider
mmv08 Mar 12, 2021
4e12f58
deploy contracts wip
mmv08 Mar 12, 2021
8fa6b16
save contract addresses to state
mmv08 Mar 15, 2021
1b65f75
save contract addresses to localstorage
mmv08 Mar 15, 2021
f84f824
deploying safe wip
mmv08 Mar 15, 2021
d0b5692
deploy safe function
mmv08 Mar 16, 2021
b9bc7c9
dep bump
mmv08 Mar 23, 2021
c4d2a27
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Mar 23, 2021
76d301e
dep bump
mmv08 Mar 23, 2021
bb7ae9b
update package json
mmv08 Mar 23, 2021
1eec182
deploy safe and redirect to safe page
mmv08 Mar 23, 2021
d3c6e15
disable btn
mmv08 Mar 23, 2021
f7330fa
safe page wip
mmv08 Mar 23, 2021
aeb56fc
type fixes
mmv08 Mar 24, 2021
d92f95c
cache provider
mmv08 Mar 24, 2021
93b07d0
sidebar wip
mmv08 Mar 24, 2021
daf89f4
sidebar wip
mmv08 Mar 24, 2021
45060a1
mui theme fixes, sidebar wip
mmv08 Mar 25, 2021
20ecf86
sidebar wip
mmv08 Mar 25, 2021
52db5a8
redirects and stuff
mmv08 Mar 25, 2021
934d663
use borderbox box sizing
mmv08 Mar 25, 2021
c874477
loading app
mmv08 Mar 26, 2021
b6faf2d
dep bump
mmv08 Mar 29, 2021
dd44e49
wip
mmv08 Mar 29, 2021
199d3fa
display safe app in an iframe
mmv08 Mar 29, 2021
48c6cd9
safe app connector
mmv08 Mar 29, 2021
1e1a71a
connector wip
mmv08 Mar 29, 2021
636ba1e
getSafeInfo handler
mmv08 Mar 30, 2021
0b3a450
Handle rpc calls
mmv08 Mar 30, 2021
de9d848
deploy multisend, tx modal wip
mmv08 Mar 31, 2021
5f07ab7
remove yarn error log
mmv08 Mar 31, 2021
3deb5b6
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Apr 2, 2021
563f781
Dep bump
mmv08 Apr 2, 2021
fdcdf17
transaction modal wip
mmv08 Apr 2, 2021
db62c94
transaction modal wip
mmv08 Apr 2, 2021
e465bd3
move connect logic to store
mmv08 Apr 5, 2021
7605772
add component for ether balance
mmv08 Apr 5, 2021
3ffcfa6
multisend encoding wip
mmv08 Apr 5, 2021
eec3683
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Apr 6, 2021
6b4c3c0
fixes
mmv08 Apr 6, 2021
a3fa85c
attempt to fix tests
mmv08 Apr 6, 2021
eb391cf
wip
mmv08 Apr 6, 2021
ad7ccd6
transaction modal wip
mmv08 Apr 7, 2021
913031e
fix buttons
mmv08 Apr 7, 2021
cd38972
Fix crash on modal close
mmv08 Apr 8, 2021
2d45faf
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Apr 8, 2021
0512108
transaction modal wip
mmv08 Apr 8, 2021
c40614e
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Apr 9, 2021
bff3536
wip
mmv08 Apr 9, 2021
c2a4020
dep bump
mmv08 Apr 12, 2021
99c1a88
add copy button, fix bytes calc
mmv08 Apr 12, 2021
fd066de
display all transactions in the tx modal wip
mmv08 Apr 12, 2021
6ed126b
wip
mmv08 Apr 12, 2021
70921ce
Tx button wip
mmv08 Apr 13, 2021
44d225c
tx modal wip
mmv08 Apr 13, 2021
b173d06
add multisend tx button
mmv08 Apr 13, 2021
cd922eb
multisend tx view
mmv08 Apr 13, 2021
ce12bf3
add transaction view
mmv08 Apr 13, 2021
58756c3
use typechain
mmv08 Apr 14, 2021
ae39f89
Type everything
mmv08 Apr 14, 2021
4b23a60
send tx wip
mmv08 Apr 14, 2021
4d78809
send transaction from an app
mmv08 Apr 15, 2021
576bd00
send transaction from an app
mmv08 Apr 15, 2021
c223054
dep bump
mmv08 Apr 15, 2021
2f985a3
remove contract types because they're autogenerated
mmv08 Apr 15, 2021
312ce6c
ignore contract types for safe-developer-ui
mmv08 Apr 15, 2021
567c44a
Eslint fixes
mmv08 Apr 15, 2021
e1cf0a5
poll ethBalance
mmv08 Apr 16, 2021
6250e1d
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Apr 26, 2021
88bda61
tests fix
mmv08 Apr 26, 2021
53c26bf
add multisend to console.info
mmv08 Apr 28, 2021
2e3ca0c
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Apr 28, 2021
faf21ee
Remove unused function
mmv08 Apr 28, 2021
22f647d
dep bump, pass safetxgas param
mmv08 Apr 28, 2021
1edbdbd
pass safetxgas, fix modal not closing
mmv08 Apr 28, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ dist
.vscode
lerna-debug.log
yalc.lock
build
build
packages/safe-apps-developer-ui/src/types/contracts/
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@
"lerna": "^4.0.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.17.0",
"@typescript-eslint/parser": "^4.17.0",
"eslint": "7.23.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-prettier": "^3.3.1",
"@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "^4.22.0",
"eslint": "7.25.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"jest": "26.6.0",
"ts-jest": "^26.5.3",
"typescript": "^4.2.3"
"typescript": "^4.2.4"
}
}
35 changes: 21 additions & 14 deletions packages/safe-apps-developer-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,36 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@gnosis.pm/safe-apps-react-sdk": "2.3.0",
"@gnosis.pm/safe-apps-sdk": "^2.3.0",
"@gnosis.pm/safe-contracts": "1.1.1-dev.2",
"@material-ui/core": "^4.11.3",
"@material-ui/core": "^4.11.4",
"@material-ui/icons": "^4.11.2",
"@testing-library/jest-dom": "^5.11.10",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^13.0.16",
"@types/styled-components": "^5.1.9",
"@walletconnect/web3-provider": "^1.4.0",
"@testing-library/react": "^11.2.6",
"@testing-library/user-event": "^13.1.5",
"@walletconnect/web3-provider": "^1.4.1",
"clsx": "^1.1.1",
"ethereum-blockies-base64": "^1.0.2",
"ethers": "^5.0.32",
"ethers": "^5.1.4",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"styled-components": "^5.2.1",
"react-spring": "^9.1.2",
"styled-components": "^5.2.3",
"web3modal": "1.9.3",
"zustand": "^3.3.3"
"zustand": "^3.4.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --passWithNoTests",
"eject": "react-scripts eject"
"eject": "react-scripts eject",
"generate-types": "yarn generate-types:safe-contracts",
"generate-types:safe-contracts": "typechain --target=ethers-v5 --outDir './src/types/contracts' '../../node_modules/@gnosis.pm/safe-contracts/build/contracts/*.json'",
"postinstall": "yarn generate-types"
},
"browserslist": {
"production": [
Expand All @@ -43,18 +47,21 @@
]
},
"devDependencies": {
"@types/jest": "^26.0.22",
"@types/node": "^14.14.37",
"@types/react": "^17.0.3",
"@typechain/ethers-v5": "^6.0.5",
"@types/jest": "^26.0.23",
"@types/node": "^15.0.1",
"@types/react": "^17.0.4",
"@types/react-dom": "^17.0.3",
"@types/react-router": "^5.1.13",
"@types/react-router-dom": "^5.1.7",
"@types/styled-components": "^5.1.9",
"eslint-config-react-app": "^6.0.0",
"eslint-plugin-flowtype": "^5.4.0",
"eslint-plugin-flowtype": "^5.7.2",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-jsx-a11y": "^6.3.1",
"eslint-plugin-react": "^7.23.1",
"eslint-plugin-react": "^7.23.2",
"eslint-plugin-react-hooks": "^4.2.0",
"typechain": "^4.0.3",
"web-vitals": "^1.1.1"
}
}
9 changes: 9 additions & 0 deletions packages/safe-apps-developer-ui/src/api/eth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ethers } from 'ethers';

const getEthBalance = async (provider: ethers.providers.BaseProvider, address: string): Promise<ethers.BigNumber> => {
const balance = provider.getBalance(address);

return balance;
};

export { getEthBalance };
11 changes: 11 additions & 0 deletions packages/safe-apps-developer-ui/src/api/safe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ethers } from 'ethers';
import { getSafeContract } from './safeContracts';

const getSafeNonce = async (signer: ethers.providers.JsonRpcSigner, safeAddress: string): Promise<ethers.BigNumber> => {
const safe = getSafeContract(safeAddress, signer);
const nonce = await safe.nonce();

return nonce;
};

export { getSafeNonce };
42 changes: 31 additions & 11 deletions packages/safe-apps-developer-ui/src/api/safeContracts.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,54 @@
import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json';
import MultiSendSol from '@gnosis.pm/safe-contracts/build/contracts/MultiSend.json';
import ProxyFactorySol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafeProxyFactory.json';
import FallbackHandlerSol from '@gnosis.pm/safe-contracts/build/contracts/FallbackManager.json';
import { JsonRpcSigner } from '@ethersproject/providers';
import { Contract, ContractFactory } from 'ethers';
import { GnosisSafe, GnosisSafeProxyFactory, MultiSend, MasterCopy, FallbackManager } from 'src/types/contracts';
mmv08 marked this conversation as resolved.
Show resolved Hide resolved

const getProxyFactoryContract = (address: string, signer: JsonRpcSigner): Contract =>
new Contract(address, ProxyFactorySol.abi, signer);
const getProxyFactoryContract = (address: string, signer: JsonRpcSigner): GnosisSafeProxyFactory =>
new Contract(address, ProxyFactorySol.abi, signer) as GnosisSafeProxyFactory;

const getSafeContract = (address: string, signer: JsonRpcSigner): Contract =>
new Contract(address, GnosisSafeSol.abi, signer);
const getSafeContract = (address: string, signer: JsonRpcSigner): GnosisSafe =>
new Contract(address, GnosisSafeSol.abi, signer) as GnosisSafe;

const deployMasterCopy = async (signer: JsonRpcSigner): Promise<Contract> => {
const getMultiSendContract = (address: string, signer: JsonRpcSigner): MultiSend =>
new Contract(address, MultiSendSol.abi, signer) as MultiSend;

const deployMasterCopy = async (signer: JsonRpcSigner): Promise<MasterCopy> => {
const factory = new ContractFactory(GnosisSafeSol.abi, GnosisSafeSol.bytecode, signer);
const masterCopy = await factory.deploy();

return masterCopy;
return masterCopy as MasterCopy;
};

const deployProxyFactory = async (signer: JsonRpcSigner): Promise<Contract> => {
const deployProxyFactory = async (signer: JsonRpcSigner): Promise<GnosisSafeProxyFactory> => {
const factory = new ContractFactory(ProxyFactorySol.abi, ProxyFactorySol.bytecode, signer);
const proxyFactory = await factory.deploy();

return proxyFactory;
return proxyFactory as GnosisSafeProxyFactory;
};

const deployFallbackHandler = async (signer: JsonRpcSigner): Promise<Contract> => {
const deployFallbackHandler = async (signer: JsonRpcSigner): Promise<FallbackManager> => {
const factory = new ContractFactory(FallbackHandlerSol.abi, FallbackHandlerSol.bytecode, signer);
const fallbackHandler = await factory.deploy();

return fallbackHandler;
return fallbackHandler as FallbackManager;
};

export { deployProxyFactory, deployFallbackHandler, deployMasterCopy, getSafeContract, getProxyFactoryContract };
const deployMultiSend = async (signer: JsonRpcSigner): Promise<MultiSend> => {
const factory = new ContractFactory(MultiSendSol.abi, MultiSendSol.bytecode, signer);
const multiSend = await factory.deploy();

return multiSend as MultiSend;
};

export {
deployProxyFactory,
deployFallbackHandler,
deployMasterCopy,
getSafeContract,
getProxyFactoryContract,
getMultiSendContract,
deployMultiSend,
};
10 changes: 10 additions & 0 deletions packages/safe-apps-developer-ui/src/api/signatures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { EMPTY_DATA } from 'src/utils/strings';

const getPreValidatedSignature = (from: string, startStr: string = EMPTY_DATA): string => {
return `${startStr}000000000000000000000000${from.replace(
EMPTY_DATA,
'',
)}000000000000000000000000000000000000000000000000000000000000000001`;
};

export { getPreValidatedSignature };
131 changes: 131 additions & 0 deletions packages/safe-apps-developer-ui/src/api/transactions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { ZERO_ADDRESS } from 'src/utils/strings';
import { SignedProposedTx } from './../types/transaction';
import { Transaction } from '@gnosis.pm/safe-apps-sdk';
import { ethers } from 'ethers';
import { getSafeContract, getMultiSendContract } from 'src/api/safeContracts';
import { ProposedTx, CreateTransactionArgs } from 'src/types/transaction';
import { getPreValidatedSignature } from './signatures';
import { getSafeNonce } from './safe';

const CALL = 0;
const DELEGATE_CALL = 1;

const executeTransaction = async (
signer: ethers.providers.JsonRpcSigner,
safeAddress: string,
{ baseGas, data, gasPrice, gasToken, operation, refundReceiver, safeTxGas, to, valueInWei, sigs }: SignedProposedTx,
): Promise<ethers.ContractTransaction> => {
const safeInstance = getSafeContract(safeAddress, signer);
const execution = await safeInstance.execTransaction(
to,
valueInWei,
data,
operation,
safeTxGas,
baseGas,
gasPrice,
gasToken,
refundReceiver,
sigs,
);

return execution;
};

const getTransactionHash = async (
signer: ethers.providers.JsonRpcSigner,
safeAddress: string,
{
baseGas,
data,
gasPrice,
gasToken,
nonce,
operation,
refundReceiver,
safeTxGas,
to,
valueInWei,
}: ProposedTx & { nonce: ethers.BigNumberish },
): Promise<string> => {
const safeInstance = getSafeContract(safeAddress, signer);

const txHash = await safeInstance.getTransactionHash(
to,
valueInWei,
data,
operation,
safeTxGas,
baseGas,
gasPrice,
gasToken,
refundReceiver,
nonce,
);

return txHash;
};

const createTransaction = async (
signer: ethers.providers.JsonRpcSigner,
safeAddress: string,
sender: string,
{
baseGas = 0,
data,
gasPrice = 0,
gasToken = ZERO_ADDRESS,
operation = CALL,
refundReceiver = ZERO_ADDRESS,
safeTxGas = 0,
to,
valueInWei,
}: CreateTransactionArgs,
): Promise<{ safeTxHash: string; tx: ethers.ContractTransaction }> => {
const senderSignature = getPreValidatedSignature(sender);
const safeNonce = await getSafeNonce(signer, safeAddress);

const tx = {
baseGas,
data,
gasPrice,
gasToken,
operation,
refundReceiver,
safeTxGas,
nonce: safeNonce,
to,
valueInWei,
sigs: senderSignature,
};

const safeTxHash = await getTransactionHash(signer, safeAddress, tx);
const executedTx = await executeTransaction(signer, safeAddress, tx);

return { safeTxHash, tx: executedTx };
};

const encodeMultiSendCall = (
signer: ethers.providers.JsonRpcSigner,
multiSendAddress: string,
txs: Transaction[],
): string => {
const multiSend = getMultiSendContract(multiSendAddress, signer);

const joinedTxs = txs
.map((tx) => {
const data = ethers.utils.arrayify(tx.data);
const encoded = ethers.utils.solidityPack(
['uint8', 'address', 'uint256', 'uint256', 'bytes'],
[0, tx.to, tx.value, data.length, data],
);
return encoded.slice(2);
})
.join('');

const encodedMultiSendCallData = multiSend.interface.encodeFunctionData('multiSend', [`0x${joinedTxs}`]);

return encodedMultiSendCallData;
};

export { CALL, DELEGATE_CALL, encodeMultiSendCall, getTransactionHash, createTransaction };
11 changes: 11 additions & 0 deletions packages/safe-apps-developer-ui/src/assets/icons/icon-arrow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions packages/safe-apps-developer-ui/src/assets/icons/icon-code.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions packages/safe-apps-developer-ui/src/components/BalanceBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import styled from 'styled-components';
import { secondaryBackground, xs } from 'src/styles/variables';

const Box = styled.p`
background: ${secondaryBackground};
padding: ${xs};
border-radius: 5px;
width: fit-content;

span {
font-weight: bold;
}
`;

type Props = {
balance: string;
symbol?: string;
};

const BalanceBox = ({ balance, symbol = 'ETH' }: Props): React.ReactElement => (
<Box>
Balance:{' '}
<span>
{balance} {symbol}
</span>
</Box>
);

export { BalanceBox };
Loading