Merge remote-tracking branch 'origin' into in_memory_wallet_unlock

This commit is contained in:
jhl-alameda 2021-04-26 21:21:59 +08:00
commit 0096fe95a0
9 changed files with 100 additions and 84 deletions

View File

@ -2,7 +2,7 @@
Example Solana wallet with support for [SPL tokens](https://spl.solana.com/token) and Serum integration.
See [sollet.io](https://www.sollet.io) for a demo.
See [sollet.io](https://www.sollet.io) or the [Sollet Chrome Extension](https://chrome.google.com/webstore/detail/sollet/fhmfendgdocmcbmfikdcogofphimnkno) for a demo.
Wallet keys are stored in `localStorage`, optionally encrypted by a password.

View File

@ -167,7 +167,7 @@ export default function AddTokenDialog({ open, onClose }) {
</React.Fragment>
) : tab === 'popular' ? (
<List disablePadding>
{popularTokens.map((tokenInfo) => (
{popularTokens.filter(tokenInfo => tokenInfo.address).map((tokenInfo) => (
<TokenListItem
key={tokenInfo.address}
tokenInfo={tokenInfo}

View File

@ -115,6 +115,7 @@ export default function MergeAccountsDialog({ open, onClose }) {
assocTokAddr,
mintGroup,
mint,
tokenInfo.decimals,
wallet,
connection,
enqueueSnackbar,
@ -242,11 +243,11 @@ async function mergeMint(
assocTokAddr,
mintAccountSet,
mint,
decimals,
wallet,
connection,
enqueueSnackbar,
) {
console.log('mint', mint, mint.toString());
if (mintAccountSet.length === 0) {
return;
}
@ -292,6 +293,7 @@ async function mergeMint(
associatedTokenAccount,
tokenAccount.account.amount,
mint,
decimals,
);
}
}

View File

@ -241,6 +241,7 @@ function NetworkSelector() {
function WalletSelector() {
const {
accounts,
derivedAccounts,
hardwareWalletAccount,
setHardwareWalletAccount,
setWalletSelector,
@ -290,7 +291,7 @@ function WalletSelector() {
onAdd={({ name, importedAccount }) => {
addAccount({ name, importedAccount });
setWalletSelector({
walletIndex: importedAccount ? undefined : accounts.length,
walletIndex: importedAccount ? undefined : derivedAccounts.length,
importedPubkey: importedAccount
? importedAccount.publicKey.toString()
: undefined,

View File

@ -43,12 +43,10 @@ const WUSDC_MINT = new PublicKey(
const USDC_MINT = new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
const WUSDT_MINT = new PublicKey(
'BQcdHdAQW1hczDbBi9hiegXAR7A98Q9jx3X3iBBBDiq4'
'BQcdHdAQW1hczDbBi9hiegXAR7A98Q9jx3X3iBBBDiq4',
);
const USDT_MINT = new PublicKey(
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'
);
const USDT_MINT = new PublicKey('Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB');
export default function SendDialog({ open, onClose, publicKey, balanceInfo }) {
const isProdNetwork = useIsProdNetwork();
@ -68,40 +66,34 @@ export default function SendDialog({ open, onClose, publicKey, balanceInfo }) {
if (mint?.equals(WUSDC_MINT)) {
return [
<Tab label="SPL WUSDC" key="spl" value="spl" />,
<Tab
label="SPL USDC"
key="wusdcToSplUsdc"
value="wusdcToSplUsdc"
/>,
<Tab label="SPL USDC" key="wusdcToSplUsdc" value="wusdcToSplUsdc" />,
<Tab label="ERC20 USDC" key="swap" value="swap" />,
]
];
} else if (mint?.equals(WUSDT_MINT)) {
return [
<Tab label="SPL WUSDT" key="spl" value="spl" />,
<Tab
label="SPL USDT"
key="wusdtToSplUsdt"
value="wusdtToSplUsdt"
/>,
<Tab label="SPL USDT" key="wusdtToSplUsdt" value="wusdtToSplUsdt" />,
<Tab label="ERC20 USDT" key="swap" value="swap" />,
]
];
} else if (localStorage.getItem('sollet-private') && mint?.equals(USDC_MINT)) {
return [
<Tab label="SPL USDC" key="spl" value="spl" />,
<Tab label="SPL WUSDC" key="usdcToSplWUsdc" value="usdcToSplWUsdc" />,
<Tab label="ERC20 USDC" key="swap" value="swap" />,
];
} else {
return [
<Tab label={`SPL ${swapCoinInfo.ticker}`} key="spl" value="spl" />,
<Tab
label={`SPL ${swapCoinInfo.ticker}`}
key="spl"
value="spl"
/>,
<Tab
label={`${
swapCoinInfo.erc20Contract ? 'ERC20' : 'Native'
} ${swapCoinInfo.ticker}`}
label={`${swapCoinInfo.erc20Contract ? 'ERC20' : 'Native'} ${
swapCoinInfo.ticker
}`}
key="swap"
value="swap"
/>,
]
];
}
}
};
return (
<>
@ -160,6 +152,16 @@ export default function SendDialog({ open, onClose, publicKey, balanceInfo }) {
onSubmitRef={onSubmitRef}
wusdtToSplUsdt
/>
) : tab === 'usdcToSplWUsdc' ? (
<SendSwapDialog
key={tab}
onClose={onClose}
publicKey={publicKey}
balanceInfo={balanceInfo}
swapCoinInfo={swapCoinInfo}
onSubmitRef={onSubmitRef}
usdcToSplWUsdc
/>
) : (
<SendSwapDialog
key={tab}
@ -259,6 +261,7 @@ function SendSplDialog({ onClose, publicKey, balanceInfo, onSubmitRef }) {
new PublicKey(destinationAddress),
amount,
balanceInfo.mint,
decimals,
null,
overrideDestinationCheck,
);
@ -309,6 +312,7 @@ function SendSwapDialog({
ethAccount,
wusdcToSplUsdc = false,
wusdtToSplUsdt = false,
usdcToSplWUsdc = false,
onSubmitRef,
}) {
const wallet = useWallet();
@ -323,11 +327,12 @@ function SendSwapDialog({
} = useForm(balanceInfo);
const { tokenName, decimals, mint } = balanceInfo;
const blockchain = wusdcToSplUsdc || wusdtToSplUsdt
? 'sol'
: swapCoinInfo.blockchain === 'sol'
? 'eth'
: swapCoinInfo.blockchain;
const blockchain =
wusdcToSplUsdc || wusdtToSplUsdt || usdcToSplWUsdc
? 'sol'
: swapCoinInfo.blockchain === 'sol'
? 'eth'
: swapCoinInfo.blockchain;
const needMetamask = blockchain === 'eth';
const [ethBalance] = useAsyncData(
@ -361,13 +366,26 @@ function SendSwapDialog({
let splUsdtWalletAddress = useWalletAddressForMint(
wusdtToSplUsdt ? USDT_MINT : null,
);
let splWUsdcWalletAddress = useWalletAddressForMint(
usdcToSplWUsdc ? WUSDC_MINT : null,
);
useEffect(() => {
if (wusdcToSplUsdc && splUsdcWalletAddress) {
setDestinationAddress(splUsdcWalletAddress);
} else if (wusdtToSplUsdt && splUsdtWalletAddress) {
setDestinationAddress(splUsdtWalletAddress);
} else if (usdcToSplWUsdc && splWUsdcWalletAddress) {
setDestinationAddress(splWUsdcWalletAddress);
}
}, [setDestinationAddress, wusdcToSplUsdc, splUsdcWalletAddress, wusdtToSplUsdt, splUsdtWalletAddress]);
}, [
setDestinationAddress,
wusdcToSplUsdc,
splUsdcWalletAddress,
wusdtToSplUsdt,
splUsdtWalletAddress,
usdcToSplWUsdc,
splWUsdcWalletAddress,
]);
async function makeTransaction() {
let amount = Math.round(parseFloat(transferAmountString) * 10 ** decimals);
@ -386,6 +404,11 @@ function SendSwapDialog({
}
if (mint?.equals(WUSDC_MINT)) {
params.wusdcToUsdc = true;
} else if (mint?.equals(USDC_MINT)) {
if (usdcToSplWUsdc) {
params.usdcToWUsdc = true;
params.coin = WUSDC_MINT.toString();
}
} else if (mint?.equals(WUSDT_MINT)) {
params.wusdtToUsdt = true;
}
@ -398,6 +421,7 @@ function SendSwapDialog({
new PublicKey(swapInfo.address),
amount,
balanceInfo.mint,
decimals,
swapInfo.memo,
);
}

View File

@ -22,6 +22,7 @@ export async function swapApiRequest(
headers['Content-Type'] = 'application/json';
params.body = JSON.stringify(body);
}
let resp = await fetch(`https://swap.sollet.io/api/${path}`, params);
return await handleSwapApiResponse(resp, ignoreUserErrors);
}

View File

@ -14,7 +14,7 @@ import {
memoInstruction,
mintTo,
TOKEN_PROGRAM_ID,
transfer,
transferChecked,
} from './instructions';
import {
ACCOUNT_LAYOUT,
@ -300,6 +300,7 @@ export async function transferTokens({
amount,
memo,
mint,
decimals,
overrideDestinationCheck,
}) {
const destinationAccountInfo = await connection.getAccountInfo(
@ -312,6 +313,8 @@ export async function transferTokens({
return await transferBetweenSplTokenAccounts({
connection,
owner,
mint,
decimals,
sourcePublicKey,
destinationPublicKey,
amount,
@ -339,6 +342,8 @@ export async function transferTokens({
return await transferBetweenSplTokenAccounts({
connection,
owner,
mint,
decimals,
sourcePublicKey,
destinationPublicKey: destinationSplTokenAccount.publicKey,
amount,
@ -353,44 +358,24 @@ export async function transferTokens({
amount,
memo,
mint,
decimals,
});
}
// SPL tokens only.
export async function transferAndClose({
connection,
owner,
sourcePublicKey,
destinationPublicKey,
amount,
}) {
const tx = createTransferBetweenSplTokenAccountsInstruction({
ownerPublicKey: owner.publicKey,
sourcePublicKey,
destinationPublicKey,
amount,
});
tx.add(
closeAccount({
source: sourcePublicKey,
destination: owner.publicKey,
owner: owner.publicKey,
}),
);
let signers = [];
return await signAndSendTransaction(connection, tx, owner, signers);
}
function createTransferBetweenSplTokenAccountsInstruction({
ownerPublicKey,
mint,
decimals,
sourcePublicKey,
destinationPublicKey,
amount,
memo,
}) {
let transaction = new Transaction().add(
transfer({
transferChecked({
source: sourcePublicKey,
mint,
decimals,
destination: destinationPublicKey,
owner: ownerPublicKey,
amount,
@ -405,6 +390,8 @@ function createTransferBetweenSplTokenAccountsInstruction({
async function transferBetweenSplTokenAccounts({
connection,
owner,
mint,
decimals,
sourcePublicKey,
destinationPublicKey,
amount,
@ -412,6 +399,8 @@ async function transferBetweenSplTokenAccounts({
}) {
const transaction = createTransferBetweenSplTokenAccountsInstruction({
ownerPublicKey: owner.publicKey,
mint,
decimals,
sourcePublicKey,
destinationPublicKey,
amount,
@ -429,6 +418,7 @@ async function createAndTransferToAccount({
amount,
memo,
mint,
decimals,
}) {
const [
createAccountInstruction,
@ -449,6 +439,8 @@ async function createAndTransferToAccount({
const transferBetweenAccountsTxn = createTransferBetweenSplTokenAccountsInstruction(
{
ownerPublicKey: owner.publicKey,
mint,
decimals,
sourcePublicKey,
destinationPublicKey: newAddress,
amount,

View File

@ -29,11 +29,6 @@ LAYOUT.addVariant(
'initializeMint',
);
LAYOUT.addVariant(1, BufferLayout.struct([]), 'initializeAccount');
LAYOUT.addVariant(
3,
BufferLayout.struct([BufferLayout.nu64('amount')]),
'transfer',
);
LAYOUT.addVariant(
7,
BufferLayout.struct([BufferLayout.nu64('amount')]),
@ -45,6 +40,11 @@ LAYOUT.addVariant(
'burn',
);
LAYOUT.addVariant(9, BufferLayout.struct([]), 'closeAccount');
LAYOUT.addVariant(
12,
BufferLayout.struct([BufferLayout.nu64('amount'), BufferLayout.u8('decimals')]),
'transferChecked',
);
const instructionMaxSpan = Math.max(
...Object.values(LAYOUT.registry).map((r) => r.span),
@ -96,16 +96,17 @@ export function initializeAccount({ account, mint, owner }) {
});
}
export function transfer({ source, destination, amount, owner }) {
export function transferChecked({ source, mint, destination, amount, decimals, owner }) {
let keys = [
{ pubkey: source, isSigner: false, isWritable: true },
{ pubkey: mint, isSigner: false, isWritable: false },
{ pubkey: destination, isSigner: false, isWritable: true },
{ pubkey: owner, isSigner: true, isWritable: false },
];
return new TransactionInstruction({
keys,
data: encodeTokenInstructionData({
transfer: { amount },
transferChecked: { amount, decimals },
}),
programId: TOKEN_PROGRAM_ID,
});

View File

@ -14,7 +14,6 @@ import {
getOwnedTokenAccounts,
nativeTransfer,
transferTokens,
transferAndClose,
} from './tokens';
import { TOKEN_PROGRAM_ID } from './tokens/instructions';
import {
@ -99,6 +98,7 @@ export class Wallet {
destination,
amount,
mint,
decimals,
memo = null,
overrideDestinationCheck = false,
) => {
@ -116,6 +116,7 @@ export class Wallet {
amount,
memo,
mint,
decimals,
overrideDestinationCheck,
});
};
@ -133,16 +134,6 @@ export class Wallet {
});
};
transferAndClose = async (source, destination, amount) => {
return await transferAndClose({
connection: this.connection,
owner: this,
sourcePublicKey: source,
destinationPublicKey: destination,
amount,
});
};
signTransaction = async (transaction) => {
return this.provider.signTransaction(transaction);
};
@ -289,9 +280,9 @@ export function WalletProvider({ children }) {
}
}
const accounts = useMemo(() => {
const [accounts, derivedAccounts] = useMemo(() => {
if (!seed) {
return [];
return [[], []];
}
const seedBuffer = Buffer.from(seed, 'hex');
@ -325,7 +316,8 @@ export function WalletProvider({ children }) {
};
});
return derivedAccounts.concat(importedAccounts);
const accounts = derivedAccounts.concat(importedAccounts);
return [accounts, derivedAccounts];
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [seed, walletCount, walletSelector, privateKeyImports, walletNames]);
@ -358,6 +350,7 @@ export function WalletProvider({ children }) {
privateKeyImports,
setPrivateKeyImports,
accounts,
derivedAccounts,
addAccount,
setAccountName,
derivationPath,
@ -475,6 +468,7 @@ export function useBalanceInfo(publicKey) {
export function useWalletSelector() {
const {
accounts,
derivedAccounts,
addAccount,
setWalletSelector,
setAccountName,
@ -484,6 +478,7 @@ export function useWalletSelector() {
return {
accounts,
derivedAccounts,
setWalletSelector,
addAccount,
setAccountName,