Merge branch 'main' into serum-v3

This commit is contained in:
jordansexton 2021-05-21 14:36:56 -05:00
commit f84a53bebe
34 changed files with 461 additions and 271 deletions

View File

@ -12,7 +12,7 @@
<defs>
<filter id="filter0_b" x="-6" y="0" width="828" height="89" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feGaussianBlur in="BackgroundImage" stdDeviation="3"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_backgroundBlur" result="shape"/>
</filter>

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -24,9 +24,10 @@ export const AppLayout = React.memo((props: any) => {
{props.children}
</Content>
<Footer>
<div className={'description-text'} style={{ color: '#2F506F' }}>
</div>
<div
className={'description-text'}
style={{ color: '#2F506F' }}
></div>
</Footer>
</Layout>
</div>

View File

@ -34,7 +34,9 @@ export const RecentTransactionsTable = (props: {
showUserTransactions?: boolean;
tokenAccounts: TokenAccount[];
}) => {
const { loading: loadingTransfers, transfers } = useWormholeTransactions(props.tokenAccounts);
const { loading: loadingTransfers, transfers } = useWormholeTransactions(
props.tokenAccounts,
);
const { provider } = useEthereum();
const bridge = useBridge();
@ -338,7 +340,6 @@ export const RecentTransactionsTable = (props: {
scrollToFirstRowOnChange: false,
x: 900,
}}
dataSource={transfers.sort((a, b) => b.date - a.date)}
columns={userColumns}
loading={loadingTransfers}

View File

@ -36,7 +36,8 @@ export const TokenSelectModal = (props: {
return tokens.filter(token => {
return (
(token.tags?.indexOf('longList') || -1) < 0 &&
token.symbol.includes(search.toUpperCase())
(token.symbol.toLowerCase().includes(search.toLowerCase()) ||
token.name.toLowerCase().includes(search.toLowerCase()))
);
});
}

View File

@ -54,8 +54,6 @@ export const Transfer = () => {
setLastTypedAccount,
} = useTokenChainPairState();
const [request, setRequest] = useState<TransferRequest>({
from: ASSET_CHAIN.Ethereum,
to: ASSET_CHAIN.Solana,
@ -85,8 +83,11 @@ export const Transfer = () => {
});
}, [A, B, mintAddress, A.info]);
const tokenAccounts = useMemo(() => userAccounts.filter(u => u.info.mint.toBase58() === request.info?.mint), [request.info?.mint])
const tokenAccounts = useMemo(
() =>
userAccounts.filter(u => u.info.mint.toBase58() === request.info?.mint),
[request.info?.mint],
);
return (
<>

View File

@ -157,7 +157,7 @@ const queryWrappedMetaAccounts = async (
if (asset.mint) {
asset.amount =
asset.mint?.info.supply.toNumber() /
Math.pow(10, asset.mint?.info.decimals) || 0;
Math.pow(10, asset.mint?.info.decimals || 0) ;
if (!asset.mint) {
throw new Error('missing mint');
@ -167,7 +167,11 @@ const queryWrappedMetaAccounts = async (
connection.onAccountChange(asset.mint?.pubkey, acc => {
cache.add(key, acc);
asset.mint = cache.get(key);
asset.amount = asset.mint?.info.supply.toNumber() || 0;
if (asset.mint) {
asset.amount =
asset.mint?.info.supply.toNumber() /
Math.pow(10, asset.mint?.info.decimals || 0);
}
setExternalAssets([...assets.values()]);
});

View File

@ -54,7 +54,9 @@ const EXCLUDED_SPL_TOKENS = ['sol', 'srm', ...EXCLUDED_COMMON_TOKENS];
export const filterModalSolTokens = (tokens: TokenInfo[]) => {
return tokens.filter(
token => EXCLUDED_SPL_TOKENS.indexOf(token.symbol.toLowerCase()) < 0,
token =>
EXCLUDED_SPL_TOKENS.indexOf(token.symbol.toLowerCase()) < 0 &&
!token.name.includes('(Sollet)'),
);
};
const EXCLUDED_ETH_TOKENS = [...EXCLUDED_COMMON_TOKENS];

View File

@ -29,8 +29,12 @@ export const HelpView = () => {
</Row>
<Row>
<Col xs={24} sm={12}>
<Button className="action-button"
onClick={() => window.open('https://github.com/certusone/wormhole', '_blank')}>
<Button
className="action-button"
onClick={() =>
window.open('https://github.com/certusone/wormhole', '_blank')
}
>
View the Code
</Button>
</Col>

View File

@ -18,11 +18,9 @@ export const AppBar = (props: {
const TopBar = (
<div className="App-Bar-right">
{props.left}
{connected ?
(
<CurrentUserBadge />
)
: (
{connected ? (
<CurrentUserBadge />
) : (
<ConnectButton
type="text"
size="large"

View File

@ -1,15 +1,15 @@
import { Button, Dropdown, Menu } from "antd";
import { ButtonProps } from "antd/lib/button";
import React from "react";
import { Button, Dropdown, Menu } from 'antd';
import { ButtonProps } from 'antd/lib/button';
import React from 'react';
import { useWallet } from './../../contexts/wallet';
export interface ConnectButtonProps extends ButtonProps, React.RefAttributes<HTMLElement> {
export interface ConnectButtonProps
extends ButtonProps,
React.RefAttributes<HTMLElement> {
allowWalletChange?: boolean;
}
export const ConnectButton = (
props: ConnectButtonProps
) => {
export const ConnectButton = (props: ConnectButtonProps) => {
const { connected, connect, select, provider } = useWallet();
const { onClick, children, disabled, allowWalletChange, ...rest } = props;
@ -17,25 +17,30 @@ export const ConnectButton = (
const menu = (
<Menu>
<Menu.Item key="3" onClick={select}>Change Wallet</Menu.Item>
<Menu.Item key="3" onClick={select}>
Change Wallet
</Menu.Item>
</Menu>
);
if(!provider || !allowWalletChange) {
return <Button
{...rest}
onClick={connected ? onClick : connect}
disabled={connected && disabled}
>
{connected ? props.children : 'Connect'}
</Button>;
if (!provider || !allowWalletChange) {
return (
<Button
{...rest}
onClick={connected ? onClick : connect}
disabled={connected && disabled}
>
{connected ? props.children : 'Connect'}
</Button>
);
}
return (
<Dropdown.Button
onClick={connected ? onClick : connect}
disabled={connected && disabled}
overlay={menu}>
onClick={connected ? onClick : connect}
disabled={connected && disabled}
overlay={menu}
>
Connect
</Dropdown.Button>
);

View File

@ -9,7 +9,11 @@ import './styles.css';
import { Popover } from 'antd';
import { Settings } from '../Settings';
export const CurrentUserBadge = (props: { showBalance?: boolean, showAddress?: boolean, iconSize?: number }) => {
export const CurrentUserBadge = (props: {
showBalance?: boolean;
showAddress?: boolean;
iconSize?: number;
}) => {
const { wallet } = useWallet();
const { account } = useNativeAccount();
@ -17,54 +21,59 @@ export const CurrentUserBadge = (props: { showBalance?: boolean, showAddress?: b
return null;
}
const iconStyle: React.CSSProperties = props.showAddress ?
{
marginLeft: '0.5rem',
display: 'flex',
width: props.iconSize,
borderRadius: 50,
const iconStyle: React.CSSProperties = props.showAddress
? {
marginLeft: '0.5rem',
display: 'flex',
width: props.iconSize,
borderRadius: 50,
}
: {
display: 'flex',
width: props.iconSize,
paddingLeft: 0,
borderRadius: 50,
};
} :{
display: 'flex',
width: props.iconSize,
paddingLeft: 0,
borderRadius: 50,
const baseWalletKey: React.CSSProperties = {
height: props.iconSize,
cursor: 'pointer',
userSelect: 'none',
};
const baseWalletKey: React.CSSProperties = { height: props.iconSize, cursor: 'pointer', userSelect: 'none' };
const walletKeyStyle: React.CSSProperties = props.showAddress ?
baseWalletKey
:{ ...baseWalletKey, paddingLeft: 0 };
const walletKeyStyle: React.CSSProperties = props.showAddress
? baseWalletKey
: { ...baseWalletKey, paddingLeft: 0 };
let name = props.showAddress ? shortenAddress(`${wallet.publicKey}`) : '';
const unknownWallet = wallet as any;
if(unknownWallet.name) {
if (unknownWallet.name) {
name = unknownWallet.name;
}
let image = <Identicon
address={wallet.publicKey?.toBase58()}
style={iconStyle}
/>;
let image = (
<Identicon address={wallet.publicKey?.toBase58()} style={iconStyle} />
);
if(unknownWallet.image) {
if (unknownWallet.image) {
image = <img src={unknownWallet.image} style={iconStyle} />;
}
return (
<div className="wallet-wrapper">
{props.showBalance && <span>
{formatNumber.format((account?.lamports || 0) / LAMPORTS_PER_SOL)} SOL
</span>}
{props.showBalance && (
<span>
{formatNumber.format((account?.lamports || 0) / LAMPORTS_PER_SOL)} SOL
</span>
)}
<Popover
placement="topRight"
title="Settings"
content={<Settings />}
trigger="click"
>
placement="topRight"
title="Settings"
content={<Settings />}
trigger="click"
>
<div className="wallet-key" style={walletKeyStyle}>
{name && (<span style={{ marginRight: '0.5rem' }}>{name}</span>)}
{name && <span style={{ marginRight: '0.5rem' }}>{name}</span>}
{image}
</div>
</Popover>

View File

@ -3,7 +3,7 @@ import { Typography } from 'antd';
import { shortenAddress } from '../../utils/utils';
export const EtherscanLink = (props: {
address: string ;
address: string;
type: string;
code?: boolean;
style?: React.CSSProperties;

View File

@ -1,7 +1,7 @@
import { Button, Popover } from "antd";
import React from "react";
import { Button, Popover } from 'antd';
import React from 'react';
import { InfoCircleOutlined } from "@ant-design/icons";
import { InfoCircleOutlined } from '@ant-design/icons';
export const Info = (props: {
text: React.ReactElement;

View File

@ -20,7 +20,6 @@ export const Identicon = (props: {
useEffect(() => {
if (address && ref.current) {
try {
ref.current.innerHTML = '';
ref.current.className = className || '';
ref.current.appendChild(
@ -29,9 +28,8 @@ export const Identicon = (props: {
parseInt(bs58.decode(address).toString('hex').slice(5, 15), 16),
),
);
} catch (err) {
// TODO
// TODO
}
}
}, [address, style, className]);

View File

@ -1,11 +1,11 @@
import React from "react";
import { Input } from "antd";
import React from 'react';
import { Input } from 'antd';
export class NumericInput extends React.Component<any, any> {
onChange = (e: any) => {
const { value } = e.target;
const reg = /^-?\d*(\.\d*)?$/;
if (reg.test(value) || value === "" || value === "-") {
if (reg.test(value) || value === '' || value === '-') {
this.props.onChange(value);
}
};
@ -17,14 +17,14 @@ export class NumericInput extends React.Component<any, any> {
if (value === undefined || value === null) return;
if (
value.charAt &&
(value.charAt(value.length - 1) === "." || value === "-")
(value.charAt(value.length - 1) === '.' || value === '-')
) {
valueTemp = value.slice(0, -1);
}
if (value.startsWith && (value.startsWith(".") || value.startsWith("-."))) {
valueTemp = valueTemp.replace(".", "0.");
if (value.startsWith && (value.startsWith('.') || value.startsWith('-.'))) {
valueTemp = valueTemp.replace('.', '0.');
}
if (valueTemp.replace) onChange?.(valueTemp.replace(/0*(\d+)/, "$1"));
if (valueTemp.replace) onChange?.(valueTemp.replace(/0*(\d+)/, '$1'));
if (onBlur) {
onBlur();
}

View File

@ -3,9 +3,7 @@ import { Button, Select } from 'antd';
import { useWallet } from '../../contexts/wallet';
import { ENDPOINTS, useConnectionConfig } from '../../contexts/connection';
import { shortenAddress } from '../../utils';
import {
CopyOutlined
} from '@ant-design/icons';
import { CopyOutlined } from '@ant-design/icons';
export const Settings = ({
additionalSettings,
@ -33,18 +31,28 @@ export const Settings = ({
{connected && (
<>
<span>Wallet:</span>
{wallet?.publicKey && (<Button
style={{ marginBottom: 5 }} onClick={() => navigator.clipboard.writeText(wallet.publicKey?.toBase58() || '')}>
<CopyOutlined />
{shortenAddress(wallet?.publicKey.toBase58())}
</Button>)}
{wallet?.publicKey && (
<Button
style={{ marginBottom: 5 }}
onClick={() =>
navigator.clipboard.writeText(
wallet.publicKey?.toBase58() || '',
)
}
>
<CopyOutlined />
{shortenAddress(wallet?.publicKey.toBase58())}
</Button>
)}
<Button onClick={select}
style={{ marginBottom: 5 }}>
<Button onClick={select} style={{ marginBottom: 5 }}>
Change
</Button>
<Button type="primary" onClick={disconnect}
style={{ marginBottom: 5 }}>
<Button
type="primary"
onClick={disconnect}
style={{ marginBottom: 5 }}
>
Disconnect
</Button>
</>

View File

@ -1,6 +1,6 @@
import React from 'react';
import { PublicKey } from '@solana/web3.js';
import {getTokenIcon, KnownTokenMap} from '../../utils';
import { getTokenIcon, KnownTokenMap } from '../../utils';
import { useConnectionConfig } from '../../contexts/connection';
import { Identicon } from '../Identicon';
@ -9,7 +9,7 @@ export const TokenIcon = (props: {
style?: React.CSSProperties;
size?: number;
className?: string;
tokenMap?: KnownTokenMap,
tokenMap?: KnownTokenMap;
}) => {
let icon: string | undefined = '';
if (props.tokenMap) {

View File

@ -1,4 +1,4 @@
import BN from "bn.js";
import BN from 'bn.js';
export const TEN = new BN(10);
export const HALF_WAD = TEN.pow(new BN(18));

View File

@ -341,7 +341,7 @@ const UseNativeAccount = () => {
return;
}
const account = await connection.getAccountInfo(wallet.publicKey)
const account = await connection.getAccountInfo(wallet.publicKey);
updateAccount(account);
subId = connection.onAccountChange(wallet.publicKey, updateAccount);
@ -351,7 +351,7 @@ const UseNativeAccount = () => {
if (subId) {
connection.removeAccountChangeListener(subId);
}
}
};
}, [setNativeAccount, wallet, wallet?.publicKey, connection, updateCache]);
return { nativeAccount };

View File

@ -1,42 +1,57 @@
import { WalletAdapter } from "@solana/wallet-base";
import { WalletAdapter } from '@solana/wallet-base';
import Wallet from "@project-serum/sol-wallet-adapter";
import { Button, Modal } from "antd";
import React, { useCallback, useContext, useEffect, useMemo, useState } from "react";
import { notify } from "./../utils/notifications";
import { useConnectionConfig } from "./connection";
import { useLocalStorageState } from "../utils/utils";
import { LedgerProvider } from "@solana/wallet-ledger";
import { SolongWalletAdapter } from "../wallet-adapters/solong";
import { PhantomWalletAdapter } from "../wallet-adapters/phantom";
import { TorusWalletAdapter } from "../wallet-adapters/torus";
import { useLocation } from "react-router";
import Wallet from '@project-serum/sol-wallet-adapter';
import { Button, Modal } from 'antd';
import React, {
useCallback,
useContext,
useEffect,
useMemo,
useState,
} from 'react';
import { notify } from './../utils/notifications';
import { useConnectionConfig } from './connection';
import { useLocalStorageState } from '../utils/utils';
import { SolongWalletAdapter } from '../wallet-adapters/solong';
import { PhantomWalletAdapter } from '../wallet-adapters/phantom';
import { TorusWalletAdapter } from '../wallet-adapters/torus';
import { useLocation } from 'react-router';
import { LedgerWalletAdapter } from '@solana/wallet-ledger';
import {MathWalletAdapter} from "../wallet-adapters/mathWallet";
const ASSETS_URL = 'https://raw.githubusercontent.com/solana-labs/oyster/main/assets/wallets/';
const ASSETS_URL =
'https://raw.githubusercontent.com/solana-labs/oyster/main/assets/wallets/';
export const WALLET_PROVIDERS = [
{
name: "Phantom",
url: "https://www.phantom.app",
name: 'Phantom',
url: 'https://www.phantom.app',
icon: `https://www.phantom.app/img/logo.png`,
adapter: PhantomWalletAdapter,
},
LedgerProvider,
{
name: "Sollet",
url: "https://www.sollet.io",
name: 'Ledger',
url: 'https://www.ledger.com',
icon: `${ASSETS_URL}ledger.svg`,
adapter: LedgerWalletAdapter,
},
{
name: 'Sollet',
url: 'https://www.sollet.io',
icon: `${ASSETS_URL}sollet.svg`,
}, {
name: "Solong",
url: "https://solongwallet.com",
},
{
name: 'Solong',
url: 'https://solongwallet.com',
icon: `${ASSETS_URL}solong.png`,
adapter: SolongWalletAdapter,
},
// TODO: enable when fully functional
// {
// name: "MathWallet",
// url: "https://mathwallet.org",
// icon: `${ASSETS_URL}mathwallet.svg`,
// },
{
name: 'MathWallet',
url: 'https://mathwallet.org',
icon: `${ASSETS_URL}mathwallet.svg`,
adapter: MathWalletAdapter,
},
// {
// name: 'Torus',
// url: 'https://tor.us',
@ -53,60 +68,79 @@ export const WALLET_PROVIDERS = [
];
const WalletContext = React.createContext<{
wallet: WalletAdapter | undefined,
connected: boolean,
select: () => void,
provider: typeof WALLET_PROVIDERS[number] | undefined,
wallet: WalletAdapter | undefined;
connected: boolean;
select: () => void;
provider: typeof WALLET_PROVIDERS[number] | undefined;
}>({
wallet: undefined,
connected: false,
select() { },
select() {},
provider: undefined,
});
export function WalletProvider({ children = null as any }) {
const { endpoint } = useConnectionConfig();
const location = useLocation();
const [autoConnect, setAutoConnect] = useState(location.pathname.indexOf('result=') >= 0 || false);
const [providerUrl, setProviderUrl] = useLocalStorageState("walletProvider");
const [autoConnect, setAutoConnect] = useState(
location.pathname.indexOf('result=') >= 0 || false,
);
const [providerUrl, setProviderUrl] = useLocalStorageState('walletProvider');
const provider = useMemo(() => WALLET_PROVIDERS.find(({ url }) => url === providerUrl), [providerUrl]);
const provider = useMemo(
() => WALLET_PROVIDERS.find(({ url }) => url === providerUrl),
[providerUrl],
);
const wallet = useMemo(function () {
if (provider) {
return new (provider.adapter || Wallet)(providerUrl, endpoint) as WalletAdapter;
}
}, [provider, providerUrl, endpoint]);
const wallet = useMemo(
function () {
if (provider) {
try {
return new (provider.adapter || Wallet)(
providerUrl,
endpoint,
) as WalletAdapter;
} catch (e) {
console.log(`Error connecting to wallet ${provider.name}: ${e}`);
return undefined;
}
}
},
[provider, providerUrl, endpoint],
);
const [connected, setConnected] = useState(false);
useEffect(() => {
if (wallet) {
wallet.on("connect", () => {
wallet.on('connect', () => {
if (wallet.publicKey) {
setConnected(true);
const walletPublicKey = wallet.publicKey.toBase58();
const keyToDisplay =
walletPublicKey.length > 20
? `${walletPublicKey.substring(0, 7)}.....${walletPublicKey.substring(
walletPublicKey.length - 7,
walletPublicKey.length
)}`
? `${walletPublicKey.substring(
0,
7,
)}.....${walletPublicKey.substring(
walletPublicKey.length - 7,
walletPublicKey.length,
)}`
: walletPublicKey;
notify({
message: "Wallet update",
description: "Connected to wallet " + keyToDisplay,
message: 'Wallet update',
description: 'Connected to wallet ' + keyToDisplay,
});
}
});
wallet.on("disconnect", () => {
wallet.on('disconnect', () => {
setConnected(false);
// setProviderUrl(null)
notify({
message: "Wallet update",
description: "Disconnected from wallet",
message: 'Wallet update',
description: 'Disconnected from wallet',
});
});
}
@ -126,7 +160,7 @@ export function WalletProvider({ children = null as any }) {
setAutoConnect(false);
}
return () => { }
return () => {};
}, [wallet, autoConnect]);
const [isModalVisible, setIsModalVisible] = useState(false);
@ -148,21 +182,22 @@ export function WalletProvider({ children = null as any }) {
title="Select Wallet"
okText="Connect"
visible={isModalVisible}
okButtonProps={{ style: { display: "none" } }}
okButtonProps={{ style: { display: 'none' } }}
onCancel={close}
width={400}>
width={400}
>
{WALLET_PROVIDERS.map((provider, idx) => {
const onClick = function () {
setProviderUrl(provider.url);
setAutoConnect(true);
close();
}
};
return (
<Button
key={idx}
size="large"
type={providerUrl === provider.url ? "primary" : "ghost"}
type={providerUrl === provider.url ? 'primary' : 'ghost'}
onClick={onClick}
icon={
<img
@ -170,15 +205,19 @@ export function WalletProvider({ children = null as any }) {
width={20}
height={20}
src={provider.icon}
style={{ marginRight: 8 }} />
style={{ marginRight: 8 }}
/>
}
style={{
display: "block",
width: "100%",
textAlign: "left",
display: 'block',
width: '100%',
textAlign: 'left',
marginBottom: 8,
}}>{provider.name}</Button>
)
}}
>
{provider.name}
</Button>
);
})}
</Modal>
</WalletContext.Provider>
@ -199,4 +238,4 @@ export const useWallet = () => {
wallet?.disconnect();
},
};
}
};

View File

@ -5,7 +5,9 @@ export const useAccountByMint = (mint?: string | PublicKey) => {
const { userAccounts } = useUserAccounts();
const mintAddress = typeof mint === 'string' ? mint : mint?.toBase58();
const index = userAccounts.findIndex((acc) => acc.info.mint.toBase58() === mintAddress);
const index = userAccounts.findIndex(
acc => acc.info.mint.toBase58() === mintAddress,
);
if (index !== -1) {
return userAccounts[index];

View File

@ -4,6 +4,7 @@ import { getTokenName } from '../utils/utils';
export function useTokenName(mintAddress?: string | PublicKey) {
const { tokenMap } = useConnectionConfig();
const address = typeof mintAddress === 'string' ? mintAddress : mintAddress?.toBase58();
const address =
typeof mintAddress === 'string' ? mintAddress : mintAddress?.toBase58();
return getTokenName(tokenMap, address);
}

View File

@ -14,7 +14,7 @@ const FEE_LAYOUT = BufferLayout.struct(
BufferLayout.nu64('hostFeeNumerator'),
BufferLayout.nu64('hostFeeDenominator'),
],
'fees'
'fees',
);
export const TokenSwapLayoutLegacyV0 = BufferLayout.struct([
@ -27,42 +27,58 @@ export const TokenSwapLayoutLegacyV0 = BufferLayout.struct([
uint64('feesDenominator'),
]);
export const TokenSwapLayoutV1: typeof BufferLayout.Structure = BufferLayout.struct([
BufferLayout.u8('isInitialized'),
BufferLayout.u8('nonce'),
publicKey('tokenProgramId'),
publicKey('tokenAccountA'),
publicKey('tokenAccountB'),
publicKey('tokenPool'),
publicKey('mintA'),
publicKey('mintB'),
publicKey('feeAccount'),
BufferLayout.u8('curveType'),
uint64('tradeFeeNumerator'),
uint64('tradeFeeDenominator'),
uint64('ownerTradeFeeNumerator'),
uint64('ownerTradeFeeDenominator'),
uint64('ownerWithdrawFeeNumerator'),
uint64('ownerWithdrawFeeDenominator'),
BufferLayout.blob(16, 'padding'),
]);
export const TokenSwapLayoutV1: typeof BufferLayout.Structure = BufferLayout.struct(
[
BufferLayout.u8('isInitialized'),
BufferLayout.u8('nonce'),
publicKey('tokenProgramId'),
publicKey('tokenAccountA'),
publicKey('tokenAccountB'),
publicKey('tokenPool'),
publicKey('mintA'),
publicKey('mintB'),
publicKey('feeAccount'),
BufferLayout.u8('curveType'),
uint64('tradeFeeNumerator'),
uint64('tradeFeeDenominator'),
uint64('ownerTradeFeeNumerator'),
uint64('ownerTradeFeeDenominator'),
uint64('ownerWithdrawFeeNumerator'),
uint64('ownerWithdrawFeeDenominator'),
BufferLayout.blob(16, 'padding'),
],
);
const CURVE_NODE = BufferLayout.union(BufferLayout.u8(), BufferLayout.blob(32), 'curve');
const CURVE_NODE = BufferLayout.union(
BufferLayout.u8(),
BufferLayout.blob(32),
'curve',
);
CURVE_NODE.addVariant(0, BufferLayout.struct([]), 'constantProduct');
CURVE_NODE.addVariant(1, BufferLayout.struct([BufferLayout.nu64('token_b_price')]), 'constantPrice');
CURVE_NODE.addVariant(
1,
BufferLayout.struct([BufferLayout.nu64('token_b_price')]),
'constantPrice',
);
CURVE_NODE.addVariant(2, BufferLayout.struct([]), 'stable');
CURVE_NODE.addVariant(3, BufferLayout.struct([BufferLayout.nu64('token_b_offset')]), 'offset');
CURVE_NODE.addVariant(
3,
BufferLayout.struct([BufferLayout.nu64('token_b_offset')]),
'offset',
);
export const TokenSwapLayout: typeof BufferLayout.Structure = BufferLayout.struct([
BufferLayout.u8('isInitialized'),
BufferLayout.u8('nonce'),
publicKey('tokenProgramId'),
publicKey('tokenAccountA'),
publicKey('tokenAccountB'),
publicKey('tokenPool'),
publicKey('mintA'),
publicKey('mintB'),
publicKey('feeAccount'),
FEE_LAYOUT,
CURVE_NODE,
]);
export const TokenSwapLayout: typeof BufferLayout.Structure = BufferLayout.struct(
[
BufferLayout.u8('isInitialized'),
BufferLayout.u8('nonce'),
publicKey('tokenProgramId'),
publicKey('tokenAccountA'),
publicKey('tokenAccountB'),
publicKey('tokenPool'),
publicKey('mintA'),
publicKey('mintB'),
publicKey('feeAccount'),
FEE_LAYOUT,
CURVE_NODE,
],
);

View File

@ -1,9 +1,9 @@
declare module "buffer-layout" {
declare module 'buffer-layout' {
const bl: any;
export = bl;
}
declare module "jazzicon" {
declare module 'jazzicon' {
const jazzicon: any;
export = jazzicon;
}

View File

@ -1,4 +1,4 @@
declare module "@project-serum/sol-wallet-adapter" {
declare module '@project-serum/sol-wallet-adapter' {
const adapter: any;
export = adapter;
}

View File

@ -1,7 +1,7 @@
import { EventEmitter as Emitter } from "eventemitter3";
import { EventEmitter as Emitter } from 'eventemitter3';
export class CacheUpdateEvent {
static type = "CacheUpdate";
static type = 'CacheUpdate';
id: string;
parser: any;
isNew: boolean;
@ -13,7 +13,7 @@ export class CacheUpdateEvent {
}
export class CacheDeleteEvent {
static type = "CacheUpdate";
static type = 'CacheUpdate';
id: string;
constructor(id: string) {
this.id = id;
@ -21,7 +21,7 @@ export class CacheDeleteEvent {
}
export class MarketUpdateEvent {
static type = "MarketUpdate";
static type = 'MarketUpdate';
ids: Set<string>;
constructor(ids: Set<string>) {
this.ids = ids;
@ -50,7 +50,7 @@ export class EventEmitter {
raiseCacheUpdated(id: string, isNew: boolean, parser: any) {
this.emitter.emit(
CacheUpdateEvent.type,
new CacheUpdateEvent(id, isNew, parser)
new CacheUpdateEvent(id, isNew, parser),
);
}

View File

@ -107,7 +107,7 @@ export const PROGRAM_IDS = [
{
name: 'devnet',
governance: () => ({
programId: new PublicKey('A9KW1nhwZUr1kMX8C6rgzZvAE9AwEEUi2C77SiVvEiuN'),
programId: new PublicKey('C3FdFYAwoAanUUHrtxnnzN8A6R13RmRoDRWmLbcpZATp'),
}),
wormhole: () => ({
pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'),

View File

@ -1,13 +1,13 @@
import React from "react";
import { notification } from "antd";
import React from 'react';
import { notification } from 'antd';
// import Link from '../components/Link';
export function notify({
message = "",
message = '',
description = undefined as any,
txid = "",
type = "info",
placement = "bottomLeft",
txid = '',
type = 'info',
placement = 'bottomLeft',
}) {
if (txid) {
// <Link
@ -21,13 +21,13 @@ export function notify({
description = <></>;
}
(notification as any)[type]({
message: <span style={{ color: "black" }}>{message}</span>,
message: <span style={{ color: 'black' }}>{message}</span>,
description: (
<span style={{ color: "black", opacity: 0.5 }}>{description}</span>
<span style={{ color: 'black', opacity: 0.5 }}>{description}</span>
),
placement,
style: {
backgroundColor: "white",
backgroundColor: 'white',
},
});
}

View File

@ -0,0 +1,92 @@
import EventEmitter from 'eventemitter3';
import { PublicKey, Transaction } from '@solana/web3.js';
import { WalletAdapter } from '@solana/wallet-base';
import { notify } from '../../utils/notifications';
export class MathWalletAdapter extends EventEmitter implements WalletAdapter {
_publicKey: PublicKey | null;
_onProcess: boolean;
_connected: boolean;
constructor() {
super();
this._publicKey = null;
this._onProcess = false;
this._connected = false;
this.connect = this.connect.bind(this);
}
get publicKey() {
return this._publicKey;
}
get connected() {
return this._connected;
}
get autoApprove() {
return false;
}
// eslint-disable-next-line
async signAllTransactions(
transactions: Transaction[],
): Promise<Transaction[]> {
if (!this._provider) {
return transactions;
}
return this._provider.signAllTransactions(transactions);
}
private get _provider() {
if ((window as any)?.solana?.isMathWallet) {
return (window as any).solana;
}
return undefined;
}
signTransaction(transaction: Transaction) {
if (!this._provider) {
return transaction;
}
return this._provider.signTransaction(transaction);
}
connect() {
if (this._onProcess) {
return;
}
if (!this._provider) {
notify({
message: 'MathWallet Error',
description:
'Please install and initialize Math wallet extension from Chrome first',
});
return;
}
this._onProcess = true;
this._provider
.getAccount()
.then((account: any) => {
this._publicKey = new PublicKey(account);
this._connected = true;
this.emit('connect', this._publicKey);
})
.catch(() => {
this.disconnect();
})
.finally(() => {
this._onProcess = false;
});
}
disconnect() {
if (this._publicKey) {
this._publicKey = null;
this._connected = false;
this.emit('disconnect');
}
}
}

View File

@ -1,7 +1,7 @@
import EventEmitter from "eventemitter3";
import {PublicKey, Transaction} from "@solana/web3.js";
import { WalletAdapter } from "@solana/wallet-base";
import { notify } from "../../utils/notifications";
import EventEmitter from 'eventemitter3';
import { PublicKey, Transaction } from '@solana/web3.js';
import { WalletAdapter } from '@solana/wallet-base';
import { notify } from '../../utils/notifications';
export class SolongWalletAdapter extends EventEmitter implements WalletAdapter {
_publicKey: PublicKey | null;
@ -32,8 +32,8 @@ export class SolongWalletAdapter extends EventEmitter implements WalletAdapter {
if ((window as any).solong === undefined) {
notify({
message: "Solong Error",
description: "Please install solong wallet from Chrome ",
message: 'Solong Error',
description: 'Please install solong wallet from Chrome ',
});
return;
}
@ -43,7 +43,7 @@ export class SolongWalletAdapter extends EventEmitter implements WalletAdapter {
.selectAccount()
.then((account: any) => {
this._publicKey = new PublicKey(account);
this.emit("connect", this._publicKey);
this.emit('connect', this._publicKey);
})
.catch(() => {
this.disconnect();
@ -56,7 +56,7 @@ export class SolongWalletAdapter extends EventEmitter implements WalletAdapter {
disconnect() {
if (this._publicKey) {
this._publicKey = null;
this.emit("disconnect");
this.emit('disconnect');
}
}
}

View File

@ -1,6 +1,6 @@
import EventEmitter from "eventemitter3";
import { PublicKey } from "@solana/web3.js";
import { notify } from "../utils/notifications";
import EventEmitter from 'eventemitter3';
import { PublicKey } from '@solana/web3.js';
import { notify } from '../utils/notifications';
export class SolongAdapter extends EventEmitter {
_publicKey: any;
@ -27,8 +27,8 @@ export class SolongAdapter extends EventEmitter {
if ((window as any).solong === undefined) {
notify({
message: "Solong Error",
description: "Please install solong wallet from Chrome ",
message: 'Solong Error',
description: 'Please install solong wallet from Chrome ',
});
return;
}
@ -38,7 +38,7 @@ export class SolongAdapter extends EventEmitter {
.selectAccount()
.then((account: any) => {
this._publicKey = new PublicKey(account);
this.emit("connect", this._publicKey);
this.emit('connect', this._publicKey);
})
.catch(() => {
this.disconnect();
@ -51,7 +51,7 @@ export class SolongAdapter extends EventEmitter {
disconnect() {
if (this._publicKey) {
this._publicKey = null;
this.emit("disconnect");
this.emit('disconnect');
}
}
}

View File

@ -1,13 +1,13 @@
import EventEmitter from "eventemitter3"
import { Account, PublicKey, Transaction } from "@solana/web3.js"
import { WalletAdapter } from "@solana/wallet-base"
import OpenLogin from "@toruslabs/openlogin"
import { getED25519Key } from "@toruslabs/openlogin-ed25519"
import EventEmitter from 'eventemitter3';
import { Account, PublicKey, Transaction } from '@solana/web3.js';
import { WalletAdapter } from '@solana/wallet-base';
import OpenLogin from '@toruslabs/openlogin';
import { getED25519Key } from '@toruslabs/openlogin-ed25519';
const getSolanaPrivateKey = (openloginKey: string)=>{
const { sk } = getED25519Key(openloginKey)
return sk
}
const getSolanaPrivateKey = (openloginKey: string) => {
const { sk } = getED25519Key(openloginKey);
return sk;
};
export class TorusWalletAdapter extends EventEmitter implements WalletAdapter {
_provider: OpenLogin | undefined;
@ -18,19 +18,21 @@ export class TorusWalletAdapter extends EventEmitter implements WalletAdapter {
name: string = '';
constructor(providerUrl: string, endpoint: string) {
super()
this.connect = this.connect.bind(this)
super();
this.connect = this.connect.bind(this);
this.endpoint = endpoint;
this.providerUrl = providerUrl;
}
async signAllTransactions(transactions: Transaction[]): Promise<Transaction[]> {
if(this.account) {
async signAllTransactions(
transactions: Transaction[],
): Promise<Transaction[]> {
if (this.account) {
let account = this.account;
transactions.forEach(t => t.partialSign(account));
}
return transactions
return transactions;
}
get publicKey() {
@ -38,25 +40,27 @@ export class TorusWalletAdapter extends EventEmitter implements WalletAdapter {
}
async signTransaction(transaction: Transaction) {
if(this.account) {
transaction.partialSign(this.account)
if (this.account) {
transaction.partialSign(this.account);
}
return transaction
return transaction;
}
connect = async () => {
const clientId = process.env.REACT_APP_CLIENT_ID || 'BNxdRWx08cSTPlzMAaShlM62d4f8Tp6racfnCg_gaH0XQ1NfSGo3h5B_IkLtgSnPMhlxsSvhqugWm0x8x-VkUXA';
const clientId =
process.env.REACT_APP_CLIENT_ID ||
'BNxdRWx08cSTPlzMAaShlM62d4f8Tp6racfnCg_gaH0XQ1NfSGo3h5B_IkLtgSnPMhlxsSvhqugWm0x8x-VkUXA';
this._provider = new OpenLogin({
clientId,
network: "testnet", // mainnet, testnet, development
uxMode: 'popup'
network: 'testnet', // mainnet, testnet, development
uxMode: 'popup',
});
try {
await this._provider.init();
} catch (ex) {
console.error('init failed', ex)
console.error('init failed', ex);
}
console.error(this._provider?.state.store);
@ -67,28 +71,30 @@ export class TorusWalletAdapter extends EventEmitter implements WalletAdapter {
this.account = new Account(secretKey);
} else {
try {
const { privKey } = await this._provider.login({ loginProvider: "unselected"} as any);
const { privKey } = await this._provider.login({
loginProvider: 'unselected',
} as any);
const secretKey = getSolanaPrivateKey(privKey);
this.account = new Account(secretKey);
} catch(ex) {
} catch (ex) {
console.error('login failed', ex);
}
}
this.name = this._provider?.state.store.get('name');;
this.name = this._provider?.state.store.get('name');
this.image = this._provider?.state.store.get('profileImage');
debugger;
this.emit("connect");
}
this.emit('connect');
};
disconnect = async () => {
console.log("Disconnecting...")
console.log('Disconnecting...');
if (this._provider) {
await this._provider.logout();
await this._provider._cleanup();
this._provider = undefined;
this.emit("disconnect");
this.emit('disconnect');
}
}
};
}

View File

@ -28,7 +28,7 @@ import { createEmptyGovernanceVotingRecordInstruction } from '../models/createEm
import { voteInstruction } from '../models/vote';
const { createTokenAccount } = actions;
const { sendTransactions } = contexts.Connection;
const { sendTransactions, SequenceType } = contexts.Connection;
const { notify } = utils;
const { approve } = models;
@ -199,8 +199,7 @@ export const depositSourceTokensAndVote = async (
wallet,
[depositInstructions, voteInstructions],
[depositSigners, voteSigners],
true,
true,
SequenceType.Sequential,
);
notify({

View File

@ -4,7 +4,12 @@ import {
Message,
TransactionInstruction,
} from '@solana/web3.js';
import { contexts, utils, ParsedAccount } from '@oyster/common';
import {
contexts,
utils,
ParsedAccount,
sendTransactionWithRetry,
} from '@oyster/common';
import {
Proposal,
@ -14,7 +19,6 @@ import {
import { executeInstruction } from '../models/execute';
import { LABELS } from '../constants';
import { getMessageAccountInfos } from '../utils/transactions';
const { sendTransaction } = contexts.Connection;
const { notify } = utils;
export const execute = async (
@ -47,12 +51,11 @@ export const execute = async (
});
try {
let tx = await sendTransaction(
let tx = await sendTransactionWithRetry(
connection,
wallet,
instructions,
signers,
true,
);
notify({