mirror of https://github.com/certusone/oyster.git
Added MathWallet Provider (#110)
* fixed ledger wallet and filtering out sollet tokens * sanity check for token amounts * added wallet adapter * added math wallet to available wallet * fixed string case * lint common package
This commit is contained in:
parent
4b1d3cfdab
commit
cf8f124f8f
|
@ -24,9 +24,10 @@ export const AppLayout = React.memo((props: any) => {
|
||||||
{props.children}
|
{props.children}
|
||||||
</Content>
|
</Content>
|
||||||
<Footer>
|
<Footer>
|
||||||
<div className={'description-text'} style={{ color: '#2F506F' }}>
|
<div
|
||||||
|
className={'description-text'}
|
||||||
</div>
|
style={{ color: '#2F506F' }}
|
||||||
|
></div>
|
||||||
</Footer>
|
</Footer>
|
||||||
</Layout>
|
</Layout>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -34,7 +34,9 @@ export const RecentTransactionsTable = (props: {
|
||||||
showUserTransactions?: boolean;
|
showUserTransactions?: boolean;
|
||||||
tokenAccounts: TokenAccount[];
|
tokenAccounts: TokenAccount[];
|
||||||
}) => {
|
}) => {
|
||||||
const { loading: loadingTransfers, transfers } = useWormholeTransactions(props.tokenAccounts);
|
const { loading: loadingTransfers, transfers } = useWormholeTransactions(
|
||||||
|
props.tokenAccounts,
|
||||||
|
);
|
||||||
const { provider } = useEthereum();
|
const { provider } = useEthereum();
|
||||||
const bridge = useBridge();
|
const bridge = useBridge();
|
||||||
|
|
||||||
|
@ -338,7 +340,6 @@ export const RecentTransactionsTable = (props: {
|
||||||
scrollToFirstRowOnChange: false,
|
scrollToFirstRowOnChange: false,
|
||||||
x: 900,
|
x: 900,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
dataSource={transfers.sort((a, b) => b.date - a.date)}
|
dataSource={transfers.sort((a, b) => b.date - a.date)}
|
||||||
columns={userColumns}
|
columns={userColumns}
|
||||||
loading={loadingTransfers}
|
loading={loadingTransfers}
|
||||||
|
|
|
@ -36,7 +36,8 @@ export const TokenSelectModal = (props: {
|
||||||
return tokens.filter(token => {
|
return tokens.filter(token => {
|
||||||
return (
|
return (
|
||||||
(token.tags?.indexOf('longList') || -1) < 0 &&
|
(token.tags?.indexOf('longList') || -1) < 0 &&
|
||||||
token.symbol.includes(search.toUpperCase())
|
(token.symbol.toLowerCase().includes(search.toLowerCase()) ||
|
||||||
|
token.name.toLowerCase().includes(search.toLowerCase()))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,8 +54,6 @@ export const Transfer = () => {
|
||||||
setLastTypedAccount,
|
setLastTypedAccount,
|
||||||
} = useTokenChainPairState();
|
} = useTokenChainPairState();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const [request, setRequest] = useState<TransferRequest>({
|
const [request, setRequest] = useState<TransferRequest>({
|
||||||
from: ASSET_CHAIN.Ethereum,
|
from: ASSET_CHAIN.Ethereum,
|
||||||
to: ASSET_CHAIN.Solana,
|
to: ASSET_CHAIN.Solana,
|
||||||
|
@ -85,8 +83,11 @@ export const Transfer = () => {
|
||||||
});
|
});
|
||||||
}, [A, B, mintAddress, A.info]);
|
}, [A, B, mintAddress, A.info]);
|
||||||
|
|
||||||
|
const tokenAccounts = useMemo(
|
||||||
const tokenAccounts = useMemo(() => userAccounts.filter(u => u.info.mint.toBase58() === request.info?.mint), [request.info?.mint])
|
() =>
|
||||||
|
userAccounts.filter(u => u.info.mint.toBase58() === request.info?.mint),
|
||||||
|
[request.info?.mint],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -157,7 +157,7 @@ const queryWrappedMetaAccounts = async (
|
||||||
if (asset.mint) {
|
if (asset.mint) {
|
||||||
asset.amount =
|
asset.amount =
|
||||||
asset.mint?.info.supply.toNumber() /
|
asset.mint?.info.supply.toNumber() /
|
||||||
Math.pow(10, asset.mint?.info.decimals) || 0;
|
Math.pow(10, asset.mint?.info.decimals || 0) ;
|
||||||
|
|
||||||
if (!asset.mint) {
|
if (!asset.mint) {
|
||||||
throw new Error('missing mint');
|
throw new Error('missing mint');
|
||||||
|
@ -167,7 +167,11 @@ const queryWrappedMetaAccounts = async (
|
||||||
connection.onAccountChange(asset.mint?.pubkey, acc => {
|
connection.onAccountChange(asset.mint?.pubkey, acc => {
|
||||||
cache.add(key, acc);
|
cache.add(key, acc);
|
||||||
asset.mint = cache.get(key);
|
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()]);
|
setExternalAssets([...assets.values()]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -54,7 +54,9 @@ const EXCLUDED_SPL_TOKENS = ['sol', 'srm', ...EXCLUDED_COMMON_TOKENS];
|
||||||
|
|
||||||
export const filterModalSolTokens = (tokens: TokenInfo[]) => {
|
export const filterModalSolTokens = (tokens: TokenInfo[]) => {
|
||||||
return tokens.filter(
|
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];
|
const EXCLUDED_ETH_TOKENS = [...EXCLUDED_COMMON_TOKENS];
|
||||||
|
|
|
@ -29,8 +29,12 @@ export const HelpView = () => {
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={24} sm={12}>
|
<Col xs={24} sm={12}>
|
||||||
<Button className="action-button"
|
<Button
|
||||||
onClick={() => window.open('https://github.com/certusone/wormhole', '_blank')}>
|
className="action-button"
|
||||||
|
onClick={() =>
|
||||||
|
window.open('https://github.com/certusone/wormhole', '_blank')
|
||||||
|
}
|
||||||
|
>
|
||||||
View the Code
|
View the Code
|
||||||
</Button>
|
</Button>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
@ -18,11 +18,9 @@ export const AppBar = (props: {
|
||||||
const TopBar = (
|
const TopBar = (
|
||||||
<div className="App-Bar-right">
|
<div className="App-Bar-right">
|
||||||
{props.left}
|
{props.left}
|
||||||
{connected ?
|
{connected ? (
|
||||||
(
|
<CurrentUserBadge />
|
||||||
<CurrentUserBadge />
|
) : (
|
||||||
)
|
|
||||||
: (
|
|
||||||
<ConnectButton
|
<ConnectButton
|
||||||
type="text"
|
type="text"
|
||||||
size="large"
|
size="large"
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import { Button, Dropdown, Menu } from "antd";
|
import { Button, Dropdown, Menu } from 'antd';
|
||||||
import { ButtonProps } from "antd/lib/button";
|
import { ButtonProps } from 'antd/lib/button';
|
||||||
import React from "react";
|
import React from 'react';
|
||||||
import { useWallet } from './../../contexts/wallet';
|
import { useWallet } from './../../contexts/wallet';
|
||||||
|
|
||||||
export interface ConnectButtonProps extends ButtonProps, React.RefAttributes<HTMLElement> {
|
export interface ConnectButtonProps
|
||||||
|
extends ButtonProps,
|
||||||
|
React.RefAttributes<HTMLElement> {
|
||||||
allowWalletChange?: boolean;
|
allowWalletChange?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ConnectButton = (
|
export const ConnectButton = (props: ConnectButtonProps) => {
|
||||||
props: ConnectButtonProps
|
|
||||||
) => {
|
|
||||||
const { connected, connect, select, provider } = useWallet();
|
const { connected, connect, select, provider } = useWallet();
|
||||||
const { onClick, children, disabled, allowWalletChange, ...rest } = props;
|
const { onClick, children, disabled, allowWalletChange, ...rest } = props;
|
||||||
|
|
||||||
|
@ -17,25 +17,30 @@ export const ConnectButton = (
|
||||||
|
|
||||||
const menu = (
|
const menu = (
|
||||||
<Menu>
|
<Menu>
|
||||||
<Menu.Item key="3" onClick={select}>Change Wallet</Menu.Item>
|
<Menu.Item key="3" onClick={select}>
|
||||||
|
Change Wallet
|
||||||
|
</Menu.Item>
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
|
|
||||||
if(!provider || !allowWalletChange) {
|
if (!provider || !allowWalletChange) {
|
||||||
return <Button
|
return (
|
||||||
{...rest}
|
<Button
|
||||||
onClick={connected ? onClick : connect}
|
{...rest}
|
||||||
disabled={connected && disabled}
|
onClick={connected ? onClick : connect}
|
||||||
>
|
disabled={connected && disabled}
|
||||||
{connected ? props.children : 'Connect'}
|
>
|
||||||
</Button>;
|
{connected ? props.children : 'Connect'}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown.Button
|
<Dropdown.Button
|
||||||
onClick={connected ? onClick : connect}
|
onClick={connected ? onClick : connect}
|
||||||
disabled={connected && disabled}
|
disabled={connected && disabled}
|
||||||
overlay={menu}>
|
overlay={menu}
|
||||||
|
>
|
||||||
Connect
|
Connect
|
||||||
</Dropdown.Button>
|
</Dropdown.Button>
|
||||||
);
|
);
|
||||||
|
|
|
@ -9,7 +9,11 @@ import './styles.css';
|
||||||
import { Popover } from 'antd';
|
import { Popover } from 'antd';
|
||||||
import { Settings } from '../Settings';
|
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 { wallet } = useWallet();
|
||||||
const { account } = useNativeAccount();
|
const { account } = useNativeAccount();
|
||||||
|
|
||||||
|
@ -17,54 +21,59 @@ export const CurrentUserBadge = (props: { showBalance?: boolean, showAddress?: b
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const iconStyle: React.CSSProperties = props.showAddress ?
|
const iconStyle: React.CSSProperties = props.showAddress
|
||||||
{
|
? {
|
||||||
marginLeft: '0.5rem',
|
marginLeft: '0.5rem',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
width: props.iconSize,
|
width: props.iconSize,
|
||||||
borderRadius: 50,
|
borderRadius: 50,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
display: 'flex',
|
||||||
|
width: props.iconSize,
|
||||||
|
paddingLeft: 0,
|
||||||
|
borderRadius: 50,
|
||||||
|
};
|
||||||
|
|
||||||
} :{
|
const baseWalletKey: React.CSSProperties = {
|
||||||
display: 'flex',
|
height: props.iconSize,
|
||||||
width: props.iconSize,
|
cursor: 'pointer',
|
||||||
paddingLeft: 0,
|
userSelect: 'none',
|
||||||
borderRadius: 50,
|
|
||||||
};
|
};
|
||||||
|
const walletKeyStyle: React.CSSProperties = props.showAddress
|
||||||
const baseWalletKey: React.CSSProperties = { height: props.iconSize, cursor: 'pointer', userSelect: 'none' };
|
? baseWalletKey
|
||||||
const walletKeyStyle: React.CSSProperties = props.showAddress ?
|
: { ...baseWalletKey, paddingLeft: 0 };
|
||||||
baseWalletKey
|
|
||||||
:{ ...baseWalletKey, paddingLeft: 0 };
|
|
||||||
|
|
||||||
let name = props.showAddress ? shortenAddress(`${wallet.publicKey}`) : '';
|
let name = props.showAddress ? shortenAddress(`${wallet.publicKey}`) : '';
|
||||||
const unknownWallet = wallet as any;
|
const unknownWallet = wallet as any;
|
||||||
if(unknownWallet.name) {
|
if (unknownWallet.name) {
|
||||||
name = unknownWallet.name;
|
name = unknownWallet.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
let image = <Identicon
|
let image = (
|
||||||
address={wallet.publicKey?.toBase58()}
|
<Identicon address={wallet.publicKey?.toBase58()} style={iconStyle} />
|
||||||
style={iconStyle}
|
);
|
||||||
/>;
|
|
||||||
|
|
||||||
if(unknownWallet.image) {
|
if (unknownWallet.image) {
|
||||||
image = <img src={unknownWallet.image} style={iconStyle} />;
|
image = <img src={unknownWallet.image} style={iconStyle} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="wallet-wrapper">
|
<div className="wallet-wrapper">
|
||||||
{props.showBalance && <span>
|
{props.showBalance && (
|
||||||
{formatNumber.format((account?.lamports || 0) / LAMPORTS_PER_SOL)} SOL
|
<span>
|
||||||
</span>}
|
{formatNumber.format((account?.lamports || 0) / LAMPORTS_PER_SOL)} SOL
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
|
||||||
<Popover
|
<Popover
|
||||||
placement="topRight"
|
placement="topRight"
|
||||||
title="Settings"
|
title="Settings"
|
||||||
content={<Settings />}
|
content={<Settings />}
|
||||||
trigger="click"
|
trigger="click"
|
||||||
>
|
>
|
||||||
<div className="wallet-key" style={walletKeyStyle}>
|
<div className="wallet-key" style={walletKeyStyle}>
|
||||||
{name && (<span style={{ marginRight: '0.5rem' }}>{name}</span>)}
|
{name && <span style={{ marginRight: '0.5rem' }}>{name}</span>}
|
||||||
{image}
|
{image}
|
||||||
</div>
|
</div>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { Typography } from 'antd';
|
||||||
import { shortenAddress } from '../../utils/utils';
|
import { shortenAddress } from '../../utils/utils';
|
||||||
|
|
||||||
export const EtherscanLink = (props: {
|
export const EtherscanLink = (props: {
|
||||||
address: string ;
|
address: string;
|
||||||
type: string;
|
type: string;
|
||||||
code?: boolean;
|
code?: boolean;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Button, Popover } from "antd";
|
import { Button, Popover } from 'antd';
|
||||||
import React from "react";
|
import React from 'react';
|
||||||
|
|
||||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
export const Info = (props: {
|
export const Info = (props: {
|
||||||
text: React.ReactElement;
|
text: React.ReactElement;
|
||||||
|
|
|
@ -20,7 +20,6 @@ export const Identicon = (props: {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (address && ref.current) {
|
if (address && ref.current) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
ref.current.innerHTML = '';
|
ref.current.innerHTML = '';
|
||||||
ref.current.className = className || '';
|
ref.current.className = className || '';
|
||||||
ref.current.appendChild(
|
ref.current.appendChild(
|
||||||
|
@ -29,9 +28,8 @@ export const Identicon = (props: {
|
||||||
parseInt(bs58.decode(address).toString('hex').slice(5, 15), 16),
|
parseInt(bs58.decode(address).toString('hex').slice(5, 15), 16),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [address, style, className]);
|
}, [address, style, className]);
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import React from "react";
|
import React from 'react';
|
||||||
import { Input } from "antd";
|
import { Input } from 'antd';
|
||||||
|
|
||||||
export class NumericInput extends React.Component<any, any> {
|
export class NumericInput extends React.Component<any, any> {
|
||||||
onChange = (e: any) => {
|
onChange = (e: any) => {
|
||||||
const { value } = e.target;
|
const { value } = e.target;
|
||||||
const reg = /^-?\d*(\.\d*)?$/;
|
const reg = /^-?\d*(\.\d*)?$/;
|
||||||
if (reg.test(value) || value === "" || value === "-") {
|
if (reg.test(value) || value === '' || value === '-') {
|
||||||
this.props.onChange(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 === undefined || value === null) return;
|
||||||
if (
|
if (
|
||||||
value.charAt &&
|
value.charAt &&
|
||||||
(value.charAt(value.length - 1) === "." || value === "-")
|
(value.charAt(value.length - 1) === '.' || value === '-')
|
||||||
) {
|
) {
|
||||||
valueTemp = value.slice(0, -1);
|
valueTemp = value.slice(0, -1);
|
||||||
}
|
}
|
||||||
if (value.startsWith && (value.startsWith(".") || value.startsWith("-."))) {
|
if (value.startsWith && (value.startsWith('.') || value.startsWith('-.'))) {
|
||||||
valueTemp = valueTemp.replace(".", "0.");
|
valueTemp = valueTemp.replace('.', '0.');
|
||||||
}
|
}
|
||||||
if (valueTemp.replace) onChange?.(valueTemp.replace(/0*(\d+)/, "$1"));
|
if (valueTemp.replace) onChange?.(valueTemp.replace(/0*(\d+)/, '$1'));
|
||||||
if (onBlur) {
|
if (onBlur) {
|
||||||
onBlur();
|
onBlur();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,7 @@ import { Button, Select } from 'antd';
|
||||||
import { useWallet } from '../../contexts/wallet';
|
import { useWallet } from '../../contexts/wallet';
|
||||||
import { ENDPOINTS, useConnectionConfig } from '../../contexts/connection';
|
import { ENDPOINTS, useConnectionConfig } from '../../contexts/connection';
|
||||||
import { shortenAddress } from '../../utils';
|
import { shortenAddress } from '../../utils';
|
||||||
import {
|
import { CopyOutlined } from '@ant-design/icons';
|
||||||
CopyOutlined
|
|
||||||
} from '@ant-design/icons';
|
|
||||||
|
|
||||||
export const Settings = ({
|
export const Settings = ({
|
||||||
additionalSettings,
|
additionalSettings,
|
||||||
|
@ -33,18 +31,28 @@ export const Settings = ({
|
||||||
{connected && (
|
{connected && (
|
||||||
<>
|
<>
|
||||||
<span>Wallet:</span>
|
<span>Wallet:</span>
|
||||||
{wallet?.publicKey && (<Button
|
{wallet?.publicKey && (
|
||||||
style={{ marginBottom: 5 }} onClick={() => navigator.clipboard.writeText(wallet.publicKey?.toBase58() || '')}>
|
<Button
|
||||||
<CopyOutlined />
|
style={{ marginBottom: 5 }}
|
||||||
{shortenAddress(wallet?.publicKey.toBase58())}
|
onClick={() =>
|
||||||
</Button>)}
|
navigator.clipboard.writeText(
|
||||||
|
wallet.publicKey?.toBase58() || '',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<CopyOutlined />
|
||||||
|
{shortenAddress(wallet?.publicKey.toBase58())}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
<Button onClick={select}
|
<Button onClick={select} style={{ marginBottom: 5 }}>
|
||||||
style={{ marginBottom: 5 }}>
|
|
||||||
Change
|
Change
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="primary" onClick={disconnect}
|
<Button
|
||||||
style={{ marginBottom: 5 }}>
|
type="primary"
|
||||||
|
onClick={disconnect}
|
||||||
|
style={{ marginBottom: 5 }}
|
||||||
|
>
|
||||||
Disconnect
|
Disconnect
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { PublicKey } from '@solana/web3.js';
|
import { PublicKey } from '@solana/web3.js';
|
||||||
import {getTokenIcon, KnownTokenMap} from '../../utils';
|
import { getTokenIcon, KnownTokenMap } from '../../utils';
|
||||||
import { useConnectionConfig } from '../../contexts/connection';
|
import { useConnectionConfig } from '../../contexts/connection';
|
||||||
import { Identicon } from '../Identicon';
|
import { Identicon } from '../Identicon';
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ export const TokenIcon = (props: {
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
size?: number;
|
size?: number;
|
||||||
className?: string;
|
className?: string;
|
||||||
tokenMap?: KnownTokenMap,
|
tokenMap?: KnownTokenMap;
|
||||||
}) => {
|
}) => {
|
||||||
let icon: string | undefined = '';
|
let icon: string | undefined = '';
|
||||||
if (props.tokenMap) {
|
if (props.tokenMap) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import BN from "bn.js";
|
import BN from 'bn.js';
|
||||||
|
|
||||||
export const TEN = new BN(10);
|
export const TEN = new BN(10);
|
||||||
export const HALF_WAD = TEN.pow(new BN(18));
|
export const HALF_WAD = TEN.pow(new BN(18));
|
||||||
|
|
|
@ -341,7 +341,7 @@ const UseNativeAccount = () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const account = await connection.getAccountInfo(wallet.publicKey)
|
const account = await connection.getAccountInfo(wallet.publicKey);
|
||||||
updateAccount(account);
|
updateAccount(account);
|
||||||
|
|
||||||
subId = connection.onAccountChange(wallet.publicKey, updateAccount);
|
subId = connection.onAccountChange(wallet.publicKey, updateAccount);
|
||||||
|
@ -351,7 +351,7 @@ const UseNativeAccount = () => {
|
||||||
if (subId) {
|
if (subId) {
|
||||||
connection.removeAccountChangeListener(subId);
|
connection.removeAccountChangeListener(subId);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}, [setNativeAccount, wallet, wallet?.publicKey, connection, updateCache]);
|
}, [setNativeAccount, wallet, wallet?.publicKey, connection, updateCache]);
|
||||||
|
|
||||||
return { nativeAccount };
|
return { nativeAccount };
|
||||||
|
|
|
@ -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 Wallet from '@project-serum/sol-wallet-adapter';
|
||||||
import { Button, Modal } from "antd";
|
import { Button, Modal } from 'antd';
|
||||||
import React, { useCallback, useContext, useEffect, useMemo, useState } from "react";
|
import React, {
|
||||||
import { notify } from "./../utils/notifications";
|
useCallback,
|
||||||
import { useConnectionConfig } from "./connection";
|
useContext,
|
||||||
import { useLocalStorageState } from "../utils/utils";
|
useEffect,
|
||||||
import { LedgerProvider } from "@solana/wallet-ledger";
|
useMemo,
|
||||||
import { SolongWalletAdapter } from "../wallet-adapters/solong";
|
useState,
|
||||||
import { PhantomWalletAdapter } from "../wallet-adapters/phantom";
|
} from 'react';
|
||||||
import { TorusWalletAdapter } from "../wallet-adapters/torus";
|
import { notify } from './../utils/notifications';
|
||||||
import { useLocation } from "react-router";
|
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 = [
|
export const WALLET_PROVIDERS = [
|
||||||
{
|
{
|
||||||
name: "Phantom",
|
name: 'Phantom',
|
||||||
url: "https://www.phantom.app",
|
url: 'https://www.phantom.app',
|
||||||
icon: `https://www.phantom.app/img/logo.png`,
|
icon: `https://www.phantom.app/img/logo.png`,
|
||||||
adapter: PhantomWalletAdapter,
|
adapter: PhantomWalletAdapter,
|
||||||
},
|
},
|
||||||
LedgerProvider,
|
|
||||||
{
|
{
|
||||||
name: "Sollet",
|
name: 'Ledger',
|
||||||
url: "https://www.sollet.io",
|
url: 'https://www.ledger.com',
|
||||||
|
icon: `${ASSETS_URL}ledger.svg`,
|
||||||
|
adapter: LedgerWalletAdapter,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Sollet',
|
||||||
|
url: 'https://www.sollet.io',
|
||||||
icon: `${ASSETS_URL}sollet.svg`,
|
icon: `${ASSETS_URL}sollet.svg`,
|
||||||
}, {
|
},
|
||||||
name: "Solong",
|
{
|
||||||
url: "https://solongwallet.com",
|
name: 'Solong',
|
||||||
|
url: 'https://solongwallet.com',
|
||||||
icon: `${ASSETS_URL}solong.png`,
|
icon: `${ASSETS_URL}solong.png`,
|
||||||
adapter: SolongWalletAdapter,
|
adapter: SolongWalletAdapter,
|
||||||
},
|
},
|
||||||
// TODO: enable when fully functional
|
// TODO: enable when fully functional
|
||||||
// {
|
{
|
||||||
// name: "MathWallet",
|
name: 'MathWallet',
|
||||||
// url: "https://mathwallet.org",
|
url: 'https://mathwallet.org',
|
||||||
// icon: `${ASSETS_URL}mathwallet.svg`,
|
icon: `${ASSETS_URL}mathwallet.svg`,
|
||||||
// },
|
adapter: MathWalletAdapter,
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// name: 'Torus',
|
// name: 'Torus',
|
||||||
// url: 'https://tor.us',
|
// url: 'https://tor.us',
|
||||||
|
@ -53,60 +68,79 @@ export const WALLET_PROVIDERS = [
|
||||||
];
|
];
|
||||||
|
|
||||||
const WalletContext = React.createContext<{
|
const WalletContext = React.createContext<{
|
||||||
wallet: WalletAdapter | undefined,
|
wallet: WalletAdapter | undefined;
|
||||||
connected: boolean,
|
connected: boolean;
|
||||||
select: () => void,
|
select: () => void;
|
||||||
provider: typeof WALLET_PROVIDERS[number] | undefined,
|
provider: typeof WALLET_PROVIDERS[number] | undefined;
|
||||||
}>({
|
}>({
|
||||||
wallet: undefined,
|
wallet: undefined,
|
||||||
connected: false,
|
connected: false,
|
||||||
select() { },
|
select() {},
|
||||||
provider: undefined,
|
provider: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
export function WalletProvider({ children = null as any }) {
|
export function WalletProvider({ children = null as any }) {
|
||||||
const { endpoint } = useConnectionConfig();
|
const { endpoint } = useConnectionConfig();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const [autoConnect, setAutoConnect] = useState(location.pathname.indexOf('result=') >= 0 || false);
|
const [autoConnect, setAutoConnect] = useState(
|
||||||
const [providerUrl, setProviderUrl] = useLocalStorageState("walletProvider");
|
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 () {
|
const wallet = useMemo(
|
||||||
if (provider) {
|
function () {
|
||||||
return new (provider.adapter || Wallet)(providerUrl, endpoint) as WalletAdapter;
|
if (provider) {
|
||||||
}
|
try {
|
||||||
}, [provider, providerUrl, endpoint]);
|
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);
|
const [connected, setConnected] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (wallet) {
|
if (wallet) {
|
||||||
wallet.on("connect", () => {
|
wallet.on('connect', () => {
|
||||||
if (wallet.publicKey) {
|
if (wallet.publicKey) {
|
||||||
setConnected(true);
|
setConnected(true);
|
||||||
const walletPublicKey = wallet.publicKey.toBase58();
|
const walletPublicKey = wallet.publicKey.toBase58();
|
||||||
const keyToDisplay =
|
const keyToDisplay =
|
||||||
walletPublicKey.length > 20
|
walletPublicKey.length > 20
|
||||||
? `${walletPublicKey.substring(0, 7)}.....${walletPublicKey.substring(
|
? `${walletPublicKey.substring(
|
||||||
walletPublicKey.length - 7,
|
0,
|
||||||
walletPublicKey.length
|
7,
|
||||||
)}`
|
)}.....${walletPublicKey.substring(
|
||||||
|
walletPublicKey.length - 7,
|
||||||
|
walletPublicKey.length,
|
||||||
|
)}`
|
||||||
: walletPublicKey;
|
: walletPublicKey;
|
||||||
|
|
||||||
notify({
|
notify({
|
||||||
message: "Wallet update",
|
message: 'Wallet update',
|
||||||
description: "Connected to wallet " + keyToDisplay,
|
description: 'Connected to wallet ' + keyToDisplay,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
wallet.on("disconnect", () => {
|
wallet.on('disconnect', () => {
|
||||||
setConnected(false);
|
setConnected(false);
|
||||||
// setProviderUrl(null)
|
// setProviderUrl(null)
|
||||||
notify({
|
notify({
|
||||||
message: "Wallet update",
|
message: 'Wallet update',
|
||||||
description: "Disconnected from wallet",
|
description: 'Disconnected from wallet',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -126,7 +160,7 @@ export function WalletProvider({ children = null as any }) {
|
||||||
setAutoConnect(false);
|
setAutoConnect(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => { }
|
return () => {};
|
||||||
}, [wallet, autoConnect]);
|
}, [wallet, autoConnect]);
|
||||||
|
|
||||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||||
|
@ -148,21 +182,22 @@ export function WalletProvider({ children = null as any }) {
|
||||||
title="Select Wallet"
|
title="Select Wallet"
|
||||||
okText="Connect"
|
okText="Connect"
|
||||||
visible={isModalVisible}
|
visible={isModalVisible}
|
||||||
okButtonProps={{ style: { display: "none" } }}
|
okButtonProps={{ style: { display: 'none' } }}
|
||||||
onCancel={close}
|
onCancel={close}
|
||||||
width={400}>
|
width={400}
|
||||||
|
>
|
||||||
{WALLET_PROVIDERS.map((provider, idx) => {
|
{WALLET_PROVIDERS.map((provider, idx) => {
|
||||||
const onClick = function () {
|
const onClick = function () {
|
||||||
setProviderUrl(provider.url);
|
setProviderUrl(provider.url);
|
||||||
setAutoConnect(true);
|
setAutoConnect(true);
|
||||||
close();
|
close();
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
key={idx}
|
key={idx}
|
||||||
size="large"
|
size="large"
|
||||||
type={providerUrl === provider.url ? "primary" : "ghost"}
|
type={providerUrl === provider.url ? 'primary' : 'ghost'}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
icon={
|
icon={
|
||||||
<img
|
<img
|
||||||
|
@ -170,15 +205,19 @@ export function WalletProvider({ children = null as any }) {
|
||||||
width={20}
|
width={20}
|
||||||
height={20}
|
height={20}
|
||||||
src={provider.icon}
|
src={provider.icon}
|
||||||
style={{ marginRight: 8 }} />
|
style={{ marginRight: 8 }}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
style={{
|
style={{
|
||||||
display: "block",
|
display: 'block',
|
||||||
width: "100%",
|
width: '100%',
|
||||||
textAlign: "left",
|
textAlign: 'left',
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
}}>{provider.name}</Button>
|
}}
|
||||||
)
|
>
|
||||||
|
{provider.name}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
</Modal>
|
</Modal>
|
||||||
</WalletContext.Provider>
|
</WalletContext.Provider>
|
||||||
|
@ -199,4 +238,4 @@ export const useWallet = () => {
|
||||||
wallet?.disconnect();
|
wallet?.disconnect();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
|
|
@ -5,7 +5,9 @@ export const useAccountByMint = (mint?: string | PublicKey) => {
|
||||||
const { userAccounts } = useUserAccounts();
|
const { userAccounts } = useUserAccounts();
|
||||||
const mintAddress = typeof mint === 'string' ? mint : mint?.toBase58();
|
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) {
|
if (index !== -1) {
|
||||||
return userAccounts[index];
|
return userAccounts[index];
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { getTokenName } from '../utils/utils';
|
||||||
|
|
||||||
export function useTokenName(mintAddress?: string | PublicKey) {
|
export function useTokenName(mintAddress?: string | PublicKey) {
|
||||||
const { tokenMap } = useConnectionConfig();
|
const { tokenMap } = useConnectionConfig();
|
||||||
const address = typeof mintAddress === 'string' ? mintAddress : mintAddress?.toBase58();
|
const address =
|
||||||
|
typeof mintAddress === 'string' ? mintAddress : mintAddress?.toBase58();
|
||||||
return getTokenName(tokenMap, address);
|
return getTokenName(tokenMap, address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ const FEE_LAYOUT = BufferLayout.struct(
|
||||||
BufferLayout.nu64('hostFeeNumerator'),
|
BufferLayout.nu64('hostFeeNumerator'),
|
||||||
BufferLayout.nu64('hostFeeDenominator'),
|
BufferLayout.nu64('hostFeeDenominator'),
|
||||||
],
|
],
|
||||||
'fees'
|
'fees',
|
||||||
);
|
);
|
||||||
|
|
||||||
export const TokenSwapLayoutLegacyV0 = BufferLayout.struct([
|
export const TokenSwapLayoutLegacyV0 = BufferLayout.struct([
|
||||||
|
@ -27,42 +27,58 @@ export const TokenSwapLayoutLegacyV0 = BufferLayout.struct([
|
||||||
uint64('feesDenominator'),
|
uint64('feesDenominator'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const TokenSwapLayoutV1: typeof BufferLayout.Structure = BufferLayout.struct([
|
export const TokenSwapLayoutV1: typeof BufferLayout.Structure = BufferLayout.struct(
|
||||||
BufferLayout.u8('isInitialized'),
|
[
|
||||||
BufferLayout.u8('nonce'),
|
BufferLayout.u8('isInitialized'),
|
||||||
publicKey('tokenProgramId'),
|
BufferLayout.u8('nonce'),
|
||||||
publicKey('tokenAccountA'),
|
publicKey('tokenProgramId'),
|
||||||
publicKey('tokenAccountB'),
|
publicKey('tokenAccountA'),
|
||||||
publicKey('tokenPool'),
|
publicKey('tokenAccountB'),
|
||||||
publicKey('mintA'),
|
publicKey('tokenPool'),
|
||||||
publicKey('mintB'),
|
publicKey('mintA'),
|
||||||
publicKey('feeAccount'),
|
publicKey('mintB'),
|
||||||
BufferLayout.u8('curveType'),
|
publicKey('feeAccount'),
|
||||||
uint64('tradeFeeNumerator'),
|
BufferLayout.u8('curveType'),
|
||||||
uint64('tradeFeeDenominator'),
|
uint64('tradeFeeNumerator'),
|
||||||
uint64('ownerTradeFeeNumerator'),
|
uint64('tradeFeeDenominator'),
|
||||||
uint64('ownerTradeFeeDenominator'),
|
uint64('ownerTradeFeeNumerator'),
|
||||||
uint64('ownerWithdrawFeeNumerator'),
|
uint64('ownerTradeFeeDenominator'),
|
||||||
uint64('ownerWithdrawFeeDenominator'),
|
uint64('ownerWithdrawFeeNumerator'),
|
||||||
BufferLayout.blob(16, 'padding'),
|
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(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(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([
|
export const TokenSwapLayout: typeof BufferLayout.Structure = BufferLayout.struct(
|
||||||
BufferLayout.u8('isInitialized'),
|
[
|
||||||
BufferLayout.u8('nonce'),
|
BufferLayout.u8('isInitialized'),
|
||||||
publicKey('tokenProgramId'),
|
BufferLayout.u8('nonce'),
|
||||||
publicKey('tokenAccountA'),
|
publicKey('tokenProgramId'),
|
||||||
publicKey('tokenAccountB'),
|
publicKey('tokenAccountA'),
|
||||||
publicKey('tokenPool'),
|
publicKey('tokenAccountB'),
|
||||||
publicKey('mintA'),
|
publicKey('tokenPool'),
|
||||||
publicKey('mintB'),
|
publicKey('mintA'),
|
||||||
publicKey('feeAccount'),
|
publicKey('mintB'),
|
||||||
FEE_LAYOUT,
|
publicKey('feeAccount'),
|
||||||
CURVE_NODE,
|
FEE_LAYOUT,
|
||||||
]);
|
CURVE_NODE,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
declare module "buffer-layout" {
|
declare module 'buffer-layout' {
|
||||||
const bl: any;
|
const bl: any;
|
||||||
export = bl;
|
export = bl;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module "jazzicon" {
|
declare module 'jazzicon' {
|
||||||
const jazzicon: any;
|
const jazzicon: any;
|
||||||
export = jazzicon;
|
export = jazzicon;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
declare module "@project-serum/sol-wallet-adapter" {
|
declare module '@project-serum/sol-wallet-adapter' {
|
||||||
const adapter: any;
|
const adapter: any;
|
||||||
export = adapter;
|
export = adapter;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { EventEmitter as Emitter } from "eventemitter3";
|
import { EventEmitter as Emitter } from 'eventemitter3';
|
||||||
|
|
||||||
export class CacheUpdateEvent {
|
export class CacheUpdateEvent {
|
||||||
static type = "CacheUpdate";
|
static type = 'CacheUpdate';
|
||||||
id: string;
|
id: string;
|
||||||
parser: any;
|
parser: any;
|
||||||
isNew: boolean;
|
isNew: boolean;
|
||||||
|
@ -13,7 +13,7 @@ export class CacheUpdateEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CacheDeleteEvent {
|
export class CacheDeleteEvent {
|
||||||
static type = "CacheUpdate";
|
static type = 'CacheUpdate';
|
||||||
id: string;
|
id: string;
|
||||||
constructor(id: string) {
|
constructor(id: string) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
@ -21,7 +21,7 @@ export class CacheDeleteEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MarketUpdateEvent {
|
export class MarketUpdateEvent {
|
||||||
static type = "MarketUpdate";
|
static type = 'MarketUpdate';
|
||||||
ids: Set<string>;
|
ids: Set<string>;
|
||||||
constructor(ids: Set<string>) {
|
constructor(ids: Set<string>) {
|
||||||
this.ids = ids;
|
this.ids = ids;
|
||||||
|
@ -50,7 +50,7 @@ export class EventEmitter {
|
||||||
raiseCacheUpdated(id: string, isNew: boolean, parser: any) {
|
raiseCacheUpdated(id: string, isNew: boolean, parser: any) {
|
||||||
this.emitter.emit(
|
this.emitter.emit(
|
||||||
CacheUpdateEvent.type,
|
CacheUpdateEvent.type,
|
||||||
new CacheUpdateEvent(id, isNew, parser)
|
new CacheUpdateEvent(id, isNew, parser),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import React from "react";
|
import React from 'react';
|
||||||
import { notification } from "antd";
|
import { notification } from 'antd';
|
||||||
// import Link from '../components/Link';
|
// import Link from '../components/Link';
|
||||||
|
|
||||||
export function notify({
|
export function notify({
|
||||||
message = "",
|
message = '',
|
||||||
description = undefined as any,
|
description = undefined as any,
|
||||||
txid = "",
|
txid = '',
|
||||||
type = "info",
|
type = 'info',
|
||||||
placement = "bottomLeft",
|
placement = 'bottomLeft',
|
||||||
}) {
|
}) {
|
||||||
if (txid) {
|
if (txid) {
|
||||||
// <Link
|
// <Link
|
||||||
|
@ -21,13 +21,13 @@ export function notify({
|
||||||
description = <></>;
|
description = <></>;
|
||||||
}
|
}
|
||||||
(notification as any)[type]({
|
(notification as any)[type]({
|
||||||
message: <span style={{ color: "black" }}>{message}</span>,
|
message: <span style={{ color: 'black' }}>{message}</span>,
|
||||||
description: (
|
description: (
|
||||||
<span style={{ color: "black", opacity: 0.5 }}>{description}</span>
|
<span style={{ color: 'black', opacity: 0.5 }}>{description}</span>
|
||||||
),
|
),
|
||||||
placement,
|
placement,
|
||||||
style: {
|
style: {
|
||||||
backgroundColor: "white",
|
backgroundColor: 'white',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import EventEmitter from "eventemitter3";
|
import EventEmitter from 'eventemitter3';
|
||||||
import {PublicKey, Transaction} from "@solana/web3.js";
|
import { PublicKey, Transaction } from '@solana/web3.js';
|
||||||
import { WalletAdapter } from "@solana/wallet-base";
|
import { WalletAdapter } from '@solana/wallet-base';
|
||||||
import { notify } from "../../utils/notifications";
|
import { notify } from '../../utils/notifications';
|
||||||
|
|
||||||
export class SolongWalletAdapter extends EventEmitter implements WalletAdapter {
|
export class SolongWalletAdapter extends EventEmitter implements WalletAdapter {
|
||||||
_publicKey: PublicKey | null;
|
_publicKey: PublicKey | null;
|
||||||
|
@ -32,8 +32,8 @@ export class SolongWalletAdapter extends EventEmitter implements WalletAdapter {
|
||||||
|
|
||||||
if ((window as any).solong === undefined) {
|
if ((window as any).solong === undefined) {
|
||||||
notify({
|
notify({
|
||||||
message: "Solong Error",
|
message: 'Solong Error',
|
||||||
description: "Please install solong wallet from Chrome ",
|
description: 'Please install solong wallet from Chrome ',
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ export class SolongWalletAdapter extends EventEmitter implements WalletAdapter {
|
||||||
.selectAccount()
|
.selectAccount()
|
||||||
.then((account: any) => {
|
.then((account: any) => {
|
||||||
this._publicKey = new PublicKey(account);
|
this._publicKey = new PublicKey(account);
|
||||||
this.emit("connect", this._publicKey);
|
this.emit('connect', this._publicKey);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
this.disconnect();
|
this.disconnect();
|
||||||
|
@ -56,7 +56,7 @@ export class SolongWalletAdapter extends EventEmitter implements WalletAdapter {
|
||||||
disconnect() {
|
disconnect() {
|
||||||
if (this._publicKey) {
|
if (this._publicKey) {
|
||||||
this._publicKey = null;
|
this._publicKey = null;
|
||||||
this.emit("disconnect");
|
this.emit('disconnect');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import EventEmitter from "eventemitter3";
|
import EventEmitter from 'eventemitter3';
|
||||||
import { PublicKey } from "@solana/web3.js";
|
import { PublicKey } from '@solana/web3.js';
|
||||||
import { notify } from "../utils/notifications";
|
import { notify } from '../utils/notifications';
|
||||||
|
|
||||||
export class SolongAdapter extends EventEmitter {
|
export class SolongAdapter extends EventEmitter {
|
||||||
_publicKey: any;
|
_publicKey: any;
|
||||||
|
@ -27,8 +27,8 @@ export class SolongAdapter extends EventEmitter {
|
||||||
|
|
||||||
if ((window as any).solong === undefined) {
|
if ((window as any).solong === undefined) {
|
||||||
notify({
|
notify({
|
||||||
message: "Solong Error",
|
message: 'Solong Error',
|
||||||
description: "Please install solong wallet from Chrome ",
|
description: 'Please install solong wallet from Chrome ',
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ export class SolongAdapter extends EventEmitter {
|
||||||
.selectAccount()
|
.selectAccount()
|
||||||
.then((account: any) => {
|
.then((account: any) => {
|
||||||
this._publicKey = new PublicKey(account);
|
this._publicKey = new PublicKey(account);
|
||||||
this.emit("connect", this._publicKey);
|
this.emit('connect', this._publicKey);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
this.disconnect();
|
this.disconnect();
|
||||||
|
@ -51,7 +51,7 @@ export class SolongAdapter extends EventEmitter {
|
||||||
disconnect() {
|
disconnect() {
|
||||||
if (this._publicKey) {
|
if (this._publicKey) {
|
||||||
this._publicKey = null;
|
this._publicKey = null;
|
||||||
this.emit("disconnect");
|
this.emit('disconnect');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import EventEmitter from "eventemitter3"
|
import EventEmitter from 'eventemitter3';
|
||||||
import { Account, PublicKey, Transaction } from "@solana/web3.js"
|
import { Account, PublicKey, Transaction } from '@solana/web3.js';
|
||||||
import { WalletAdapter } from "@solana/wallet-base"
|
import { WalletAdapter } from '@solana/wallet-base';
|
||||||
import OpenLogin from "@toruslabs/openlogin"
|
import OpenLogin from '@toruslabs/openlogin';
|
||||||
import { getED25519Key } from "@toruslabs/openlogin-ed25519"
|
import { getED25519Key } from '@toruslabs/openlogin-ed25519';
|
||||||
|
|
||||||
const getSolanaPrivateKey = (openloginKey: string)=>{
|
const getSolanaPrivateKey = (openloginKey: string) => {
|
||||||
const { sk } = getED25519Key(openloginKey)
|
const { sk } = getED25519Key(openloginKey);
|
||||||
return sk
|
return sk;
|
||||||
}
|
};
|
||||||
|
|
||||||
export class TorusWalletAdapter extends EventEmitter implements WalletAdapter {
|
export class TorusWalletAdapter extends EventEmitter implements WalletAdapter {
|
||||||
_provider: OpenLogin | undefined;
|
_provider: OpenLogin | undefined;
|
||||||
|
@ -18,19 +18,21 @@ export class TorusWalletAdapter extends EventEmitter implements WalletAdapter {
|
||||||
name: string = '';
|
name: string = '';
|
||||||
|
|
||||||
constructor(providerUrl: string, endpoint: string) {
|
constructor(providerUrl: string, endpoint: string) {
|
||||||
super()
|
super();
|
||||||
this.connect = this.connect.bind(this)
|
this.connect = this.connect.bind(this);
|
||||||
this.endpoint = endpoint;
|
this.endpoint = endpoint;
|
||||||
this.providerUrl = providerUrl;
|
this.providerUrl = providerUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
async signAllTransactions(transactions: Transaction[]): Promise<Transaction[]> {
|
async signAllTransactions(
|
||||||
if(this.account) {
|
transactions: Transaction[],
|
||||||
|
): Promise<Transaction[]> {
|
||||||
|
if (this.account) {
|
||||||
let account = this.account;
|
let account = this.account;
|
||||||
transactions.forEach(t => t.partialSign(account));
|
transactions.forEach(t => t.partialSign(account));
|
||||||
}
|
}
|
||||||
|
|
||||||
return transactions
|
return transactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
get publicKey() {
|
get publicKey() {
|
||||||
|
@ -38,25 +40,27 @@ export class TorusWalletAdapter extends EventEmitter implements WalletAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
async signTransaction(transaction: Transaction) {
|
async signTransaction(transaction: Transaction) {
|
||||||
if(this.account) {
|
if (this.account) {
|
||||||
transaction.partialSign(this.account)
|
transaction.partialSign(this.account);
|
||||||
}
|
}
|
||||||
|
|
||||||
return transaction
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
connect = async () => {
|
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({
|
this._provider = new OpenLogin({
|
||||||
clientId,
|
clientId,
|
||||||
network: "testnet", // mainnet, testnet, development
|
network: 'testnet', // mainnet, testnet, development
|
||||||
uxMode: 'popup'
|
uxMode: 'popup',
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this._provider.init();
|
await this._provider.init();
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
console.error('init failed', ex)
|
console.error('init failed', ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error(this._provider?.state.store);
|
console.error(this._provider?.state.store);
|
||||||
|
@ -67,28 +71,30 @@ export class TorusWalletAdapter extends EventEmitter implements WalletAdapter {
|
||||||
this.account = new Account(secretKey);
|
this.account = new Account(secretKey);
|
||||||
} else {
|
} else {
|
||||||
try {
|
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);
|
const secretKey = getSolanaPrivateKey(privKey);
|
||||||
this.account = new Account(secretKey);
|
this.account = new Account(secretKey);
|
||||||
} catch(ex) {
|
} catch (ex) {
|
||||||
console.error('login failed', 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');
|
this.image = this._provider?.state.store.get('profileImage');
|
||||||
debugger;
|
debugger;
|
||||||
|
|
||||||
this.emit("connect");
|
this.emit('connect');
|
||||||
}
|
};
|
||||||
|
|
||||||
disconnect = async () => {
|
disconnect = async () => {
|
||||||
console.log("Disconnecting...")
|
console.log('Disconnecting...');
|
||||||
if (this._provider) {
|
if (this._provider) {
|
||||||
await this._provider.logout();
|
await this._provider.logout();
|
||||||
await this._provider._cleanup();
|
await this._provider._cleanup();
|
||||||
this._provider = undefined;
|
this._provider = undefined;
|
||||||
this.emit("disconnect");
|
this.emit('disconnect');
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue