Merge remote-tracking branch 'origin' into in_memory_wallet_unlock
This commit is contained in:
commit
0096fe95a0
|
@ -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.
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue