mirror of
https://github.com/AthanorLabs/atomic-swap.git
synced 2026-01-08 21:58:07 -05:00
Metamask store cleanup and bring back success message (#129)
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[
|
||||
"ws://localhost:8081",
|
||||
"ws://localhost:8082"
|
||||
"ws://localhost:8082",
|
||||
"ws://localhost:8080"
|
||||
]
|
||||
@@ -45,7 +45,7 @@ export default {
|
||||
},
|
||||
plugins: [
|
||||
json({
|
||||
compact: true
|
||||
compact: true,
|
||||
}),
|
||||
svelte({
|
||||
preprocess: sveltePreprocess({ sourceMap: !production }),
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
3
ui/src/types/Cancel.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export type CancelResult = {
|
||||
status: 'Success' | 'Aborted' | 'Refunded'
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
export type NetTakeOfferSyncResult = {
|
||||
status: 'success' | 'aborted' | 'refunded'
|
||||
status: 'Success' | 'Aborted' | 'Refunded'
|
||||
id: number
|
||||
}
|
||||
@@ -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 => {
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"baseUrl": "."
|
||||
"baseUrl": ".",
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules/*", "__sapper__/*", "public/*"]
|
||||
|
||||
2839
ui/yarn.lock
2839
ui/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user