Metamask store cleanup and bring back success message (#129)

This commit is contained in:
Thibaut Sardan
2022-06-15 05:05:21 +02:00
committed by GitHub
parent cca0b6c771
commit 7ae4dcbbbe
15 changed files with 1549 additions and 1523 deletions

View File

@@ -104,7 +104,7 @@ func (s *ExternalSender) AddID(id types.Hash) {
s.Lock()
defer s.Unlock()
_, has := s.swaps[id]
if !has {
if has {
return
}

View File

@@ -3,6 +3,7 @@ package rpc
import (
"fmt"
"net/http"
"strings"
"time"
"github.com/noot/atomic-swap/common"
@@ -132,7 +133,7 @@ func (s *NetService) takeOffer(multiaddr, offerID string,
offer *types.Offer
)
for _, maybeOffer := range queryResp.Offers {
if maybeOffer.GetID().String() == offerID {
if strings.Compare(maybeOffer.GetID().String(), offerID) == 0 {
found = true
offer = maybeOffer
break
@@ -145,7 +146,7 @@ func (s *NetService) takeOffer(multiaddr, offerID string,
swapState, err := s.xmrtaker.InitiateProtocol(providesAmount, offer)
if err != nil {
return nil, "", err
return nil, "", fmt.Errorf("failed to initiate protocol: %w", err)
}
skm, err := swapState.SendKeysMessage()

View File

@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/noot/atomic-swap/common/rpctypes"
"github.com/noot/atomic-swap/common/types"
@@ -192,6 +193,10 @@ func (s *wsServer) handleSigner(ctx context.Context, conn *websocket.Conn, offer
for {
select {
// TODO: check if conn closes or swap exited
case <-time.After(time.Minute): // TODO: vary timeout based on env
_ = conn.Close()
return fmt.Errorf("signer timed out")
case <-ctx.Done():
return nil
case tx := <-txsOutCh:

View File

@@ -4,7 +4,7 @@
MONERO_DIR="../monero-x86_64-linux-gnu-v0.17.3.0"
# either a TMPDIR is set, or use /tmp
LOG_DIR=${TMPDIR:-"/tmp"}
ALICE_P2P_ADDRESS="12D3KooWF5dTdfrVv6oFwGGGyobfxtZBVhVR654wt5ED6PU1SBqd"
ALICE_P2P_ADDRESS="12D3KooWBD82zGTFqk6Qmu5zeS6dQfiaAcn8go2QWE29HPmRX3yB"
echo "cleanup"
pkill -e -f monero;
@@ -25,7 +25,7 @@ echo "Zzz... 10s"
sleep 10
echo "mine blocks for XMRMaker"
curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"generateblocks","params":{"wallet_address":"45GcPCBQgCG3tYcYqLdj4iQixpDZYw1MGew4PH1rthp9X2YrB2c2dty1r7SwhbCXw1RJMvfy8cW1UXyeESTAuLkV5bTrZRe","amount_of_blocks":100}' -H 'Content-Type: application/json' &> $LOG_DIR/block-mining-bob.log &
curl -X POST http://127.0.0.1:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"generateblocks","params":{"wallet_address":"43wote1FPHrQQL35p3LMbNGi4J6zLcwUF9EZiw2xKfyzbQVhFXQ3VcmFuM4RDK7gxh8FGgN2C3ssXcSeJR2wY2Gx92b5gxn","amount_of_blocks":100}' -H 'Content-Type: application/json' &> $LOG_DIR/block-mining-bob.log &
echo "Zzz... 15s"
sleep 15
@@ -37,7 +37,7 @@ echo "start monero-wallet-rpc for XMRMaker on port 18083"
./monero-wallet-rpc --rpc-bind-port 18083 --password "" --disable-rpc-login --wallet-dir . &> $LOG_DIR/bob-wallet-rpc.log &
echo "launch XMRTaker swapd"
../swapd --dev-xmrtaker &> $LOG_DIR/alice-swapd.log &
../swapd --dev-xmrtaker --external-signer --contract-address 0xe78A0F7E598Cc8b0Bb87894B0F60dD2a88d6a8Ab &> $LOG_DIR/alice-swapd.log &
echo "Zzz... 10s"
sleep 10

View File

@@ -3,12 +3,12 @@
# install monero and run daemon and wallet RPC servers for alice and bob
bash ./scripts/install-monero-linux.sh
echo "starting monerod..."
./monero-x86_64-linux-gnu-v0.17.3.2/monerod --detach --regtest --offline --fixed-difficulty=1 --rpc-bind-port 18081 &
./monero-x86_64-linux-gnu-v0.17.3.0/monerod --detach --regtest --offline --fixed-difficulty=1 --rpc-bind-port 18081 --keep-fakechain &
sleep 5
echo "starting monero-wallet-rpc on port 18083..."
mkdir bob-test-keys
./monero-x86_64-linux-gnu-v0.17.3.2/monero-wallet-rpc --rpc-bind-port 18083 --disable-rpc-login --wallet-dir ./bob-test-keys &> monero-wallet-cli-bob.log &
./monero-x86_64-linux-gnu-v0.17.3.0/monero-wallet-rpc --rpc-bind-port 18083 --disable-rpc-login --wallet-dir ./bob-test-keys &> monero-wallet-cli-bob.log &
MONERO_WALLET_CLI_BOB_PID=$!
sleep 5
@@ -16,7 +16,7 @@ curl http://localhost:18083/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"cre
echo "starting monero-wallet-rpc on port 18084..."
mkdir alice-test-keys
./monero-x86_64-linux-gnu-v0.17.3.2/monero-wallet-rpc --rpc-bind-port 18084 --disable-rpc-login --wallet-dir ./alice-test-keys &> monero-wallet-cli-alice.log &
./monero-x86_64-linux-gnu-v0.17.3.0/monero-wallet-rpc --rpc-bind-port 18084 --disable-rpc-login --wallet-dir ./alice-test-keys &> monero-wallet-cli-alice.log &
MONERO_WALLET_CLI_ALICE_PID=$!
# install ganache and run

View File

@@ -1,4 +1,5 @@
[
"ws://localhost:8081",
"ws://localhost:8082"
"ws://localhost:8082",
"ws://localhost:8080"
]

View File

@@ -45,7 +45,7 @@ export default {
},
plugins: [
json({
compact: true
compact: true,
}),
svelte({
preprocess: sveltePreprocess({ sourceMap: !production }),

View File

@@ -13,11 +13,8 @@
getPeers()
}
let account = null;
const connectMetamask = () => {
connectAccount()
account = $currentAccount
}
</script>
@@ -36,7 +33,11 @@
<Button on:click={handleRefreshClick}>Refresh</Button>
</Cell>
<Cell class="metamask">
<Button on:click={connectMetamask}>{account === null ? 'Connect Metamask' : `Metamask connected: ${account}`}</Button>
{#if $currentAccount}
Account: {$currentAccount}
{:else}
<Button on:click={connectMetamask}>Connect Metamask</Button>
{/if}
</Cell>
</InnerGrid>
<br />

View File

@@ -1,6 +1,7 @@
<script lang="ts">
import Dialog, { Title, Content, Actions } from '@smui/dialog'
import Button, { Label } from '@smui/button'
import type { CancelResult } from 'src/types/Cancel'
import type { NetTakeOfferSyncResult } from 'src/types/NetTakeOfferSync'
import { getCorrespondingToken, rpcRequest } from 'src/utils'
import { selectedOffer } from '../stores/offerStore'
@@ -11,13 +12,12 @@
import { Svg } from '@smui/common/elements'
import CircularProgress from '@smui/circular-progress'
import HelperText from '@smui/textfield/helper-text'
import { currentAccount, sign } from "../stores/metamask"
import { onMount } from 'svelte'
import { currentAccount, sign } from '../stores/metamask'
const WS_ADDRESS = 'ws://127.0.0.1:8081'
let amountProvided: number | null = null
let xmrAddress = ""
let xmrAddress = ''
let isSuccess = false
let isLoadingSwap = false
let error = ''
@@ -49,67 +49,82 @@
}
const handleSendTakeOffer = () => {
let offerID = $selectedOffer?.id
let webSocket = new WebSocket(WS_ADDRESS)
const offerID = $selectedOffer?.id
const webSocket = new WebSocket(WS_ADDRESS)
webSocket.onopen = () => {
console.log('opened')
console.log("sending ws signer msg")
let req = {
method: "signer_subscribe",
console.log('sending ws signer msg')
const req = {
jsonRPC: '2.0',
id: 0,
method: 'signer_subscribe',
params: {
jsonRPC: "2.0",
id: "0",
offerID: offerID,
offerID,
ethAddress: $currentAccount,
xmrAddress: xmrAddress,
}
xmrAddress,
},
}
webSocket.send(JSON.stringify(req))
console.log("sent ws signer msg", req)
console.log('sent ws signer msg', req)
}
webSocket.onmessage = async (msg) => {
console.log('message to sign:', msg.data)
let txHash = await sign(msg.data)
let out = {
offerID: offerID,
txHash: txHash,
const txHash = await sign(msg.data)
console.log('signed txHash', txHash)
if (txHash == "") {
// tx failed, cancel swap
rpcRequest<CancelResult | undefined>('swap_cancel', {
offerID,
}).then( ({result}) => {
console.log("cancelled swap")
})
}
const out = {
offerID,
txHash,
}
webSocket.send(JSON.stringify(out))
}
webSocket.onclose = (e) => {
console.log('closed:', e)
}
webSocket.onerror = (e) => {
console.log('error', e)
}
isLoadingSwap = true
rpcRequest<NetTakeOfferSyncResult | undefined>('net_takeOfferSync', {
multiaddr: $selectedOffer?.peer,
offerID: offerID,
offerID,
providesAmount: Number(amountProvided),
})
.then(({ result }) => {
if (result?.status === 'success') {
console.log('result NetTakeOfferSyncResult', result)
if (result?.status === 'Success') {
isSuccess = true
getPeers()
} else if (result?.status === 'aborted') {
} else if (result?.status === 'Aborted') {
swapError = 'Something went wrong. Please check your node logs'
} else if (result?.status === 'refunded') {
} else if (result?.status === 'Refunded') {
swapError =
'Something went wrong. Swap funds refunded, please check the logs for more info'
}
webSocket.close()
})
.catch((e: Error) => {
console.error('error when swapping', e)
swapError = e.message
})
.finally(() => (isLoadingSwap = false))
.finally(() => {
// webSocket.close()
isLoadingSwap = false
})
}
const onReset = (resetOffer = true) => {
@@ -133,7 +148,6 @@
<Title class="title" id="mandatory-title">
Swap offer {$selectedOffer.id}
</Title>
<span>{$selectedOffer.peer}</span>
</div>
<Content id="mandatory-content">
<section class="container">
@@ -172,11 +186,8 @@
<Textfield
bind:value={xmrAddress}
variant="outlined"
label={"XMR address"}
invalid={!!error}
>
<HelperText slot="helper">{error}</HelperText>
</Textfield>
label={'XMR address'}
/>
<Icon class="swapIcon" component={Svg} viewBox="0 0 24 24">
<path fill="currentColor" d={mdiSwapVertical} />
</Icon>

View File

@@ -1,73 +1,69 @@
import {providers, Contract, utils} from "ethers"
import {providers, utils} from "ethers"
import detectEthereumProvider from "@metamask/detect-provider"
import { writable } from 'svelte/store';
import SwapFactory from "../../../ethereum/artifacts/contracts/SwapFactory.sol/SwapFactory.json"
ethereum.on('chainChanged', (_chainId) => window.location.reload());
ethereum.on('accountsChanged', handleAccountsChanged);
export const currentAccount = writable("");
export const currentAccount = writable(null);
export const connectAccount = async () => {
const provider = (await detectEthereumProvider()) as any
if (provider) {
startApp(provider);
await provider.request({ method: "eth_accounts" }).then(handleAccountsChanged)
.catch((err) => {
// Some unexpected error.
// For backwards compatibility reasons, if no accounts are available,
// eth_accounts will return an empty array.
console.error(err);
});
await initialize()
} else {
console.error("Metamask is not installed")
// detect provider using @metamask/detect-provider
detectEthereumProvider()
.then((provider) => {
if (!provider) {
console.log('Please install MetaMask!');
return
}
provider.on('accountsChanged', handleAccountsChanged);
provider.on('chainChanged', () => window.location.reload());
checkConnection();
})
export function connectAccount() {
if (!window.ethereum) return
window.ethereum
.request({ method: 'eth_requestAccounts'})
.then(handleAccountsChanged)
.catch((err: any) => {
if (err.code === 4001) {
console.log('Please connect to MetaMask.');
} else {
console.error(err);
}
});
}
function startApp(provider) {
// If the provider returned by detectEthereumProvider is not the same as
// window.ethereum, something is overwriting it, perhaps another wallet.
if (provider !== window.ethereum) {
console.error('Do you have multiple wallets installed?');
}
// Access the decentralized web!
function checkConnection() {
if (!window.ethereum) return
window.ethereum
.request({ method: 'eth_accounts' })
.then(handleAccountsChanged)
.catch(console.error);
}
// Note that this event is emitted on page load.
// If the array of accounts is non-empty, you're already
// connected.
ethereum.on('accountsChanged', handleAccountsChanged);
// For now, 'eth_accounts' will continue to always return an array
function handleAccountsChanged(accounts) {
const handleAccountsChanged = (accounts: string[]) => {
if (accounts.length === 0) {
// MetaMask is locked or the user has not connected any accounts
console.log('Please connect to MetaMask.');
} else if (accounts[0] !== currentAccount) {
currentAccount.set(accounts[0]);
console.log(currentAccount)
console.log(accounts[0])
// Do any other work!
return
}
currentAccount.set(accounts[0]);
}
let ethersProvider
let chainId
let contract
let signer
let from
export const sign = async (msg: string) => {
if(!window.ethereum){
console.error('no window.ethereum')
return
}
const initialize = async () => {
ethersProvider = new providers.Web3Provider(window.ethereum, 'any');
window.ethersProvider = ethersProvider
signer = ethersProvider.getSigner()
console.log("signer:", await signer.getAddress())
}
export const sign = async(msg) => {
let tx = JSON.parse(msg)
const ethersProvider = new providers.Web3Provider(window.ethereum, 'any');
const tx = JSON.parse(msg)
const signer = ethersProvider.getSigner()
console.log('signer...', signer)
let value
if (tx.value != "") {
value = utils.parseEther(tx.value)
}
@@ -76,9 +72,9 @@ export const sign = async(msg) => {
{
from: signer.getAddress(),
to: tx.to,
gasPrice: window.ethersProvider.getGasPrice(),
gasPrice: ethersProvider.getGasPrice(),
gasLimit: "200000",
value: value,
value,
data: tx.data,
}
@@ -93,4 +89,4 @@ export const sign = async(msg) => {
}
return res.hash
}
}

3
ui/src/types/Cancel.ts Normal file
View File

@@ -0,0 +1,3 @@
export type CancelResult = {
status: 'Success' | 'Aborted' | 'Refunded'
}

View File

@@ -1,5 +1,5 @@
export type NetTakeOfferSyncResult = {
status: 'success' | 'aborted' | 'refunded'
status: 'Success' | 'Aborted' | 'Refunded'
id: number
}

View File

@@ -4,9 +4,9 @@ export type JSONRPCResult<Data> = {
id: string
jsonrpc: string
result: Data
error: string
}
// Create a instance of axios to use the same base url.
const axiosAPI = axios.create({
baseURL: "http://127.0.0.1:5001",
@@ -22,6 +22,8 @@ export const rpcRequest = <TypeResult = any>(method: string, params: Record<stri
{ headers }
)
.then(res => {
// TODO: check res.data.error and propagate
console.log(res.data);
return Promise.resolve(res.data);
})
.catch(err => {

View File

@@ -2,7 +2,8 @@
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"strict": true,
"baseUrl": "."
"baseUrl": ".",
"esModuleInterop": true
},
"include": ["src/**/*"],
"exclude": ["node_modules/*", "__sapper__/*", "public/*"]

File diff suppressed because it is too large Load Diff