Wormhole wrapped token convert
This commit is contained in:
parent
66fc4e2735
commit
2d77694c19
|
@ -1,5 +1,5 @@
|
|||
language: node_js
|
||||
node_js: 10
|
||||
node_js: 14
|
||||
dist: bionic
|
||||
cache: yarn
|
||||
script: yarn build
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"@material-ui/core": "^4.11.2",
|
||||
"@material-ui/icons": "^4.11.2",
|
||||
"@project-serum/serum": "^0.13.33",
|
||||
"@project-serum/swap": "^0.0.11",
|
||||
"@solana/spl-token-registry": "^0.2.1",
|
||||
"@solana/web3.js": "^0.87.2",
|
||||
"@testing-library/jest-dom": "^5.11.6",
|
||||
|
|
|
@ -507,7 +507,7 @@ function BalanceListItemDetails({
|
|||
const [sendDialogOpen, setSendDialogOpen] = useState(false);
|
||||
const [depositDialogOpen, setDepositDialogOpen] = useState(false);
|
||||
const [tokenInfoDialogOpen, setTokenInfoDialogOpen] = useState(false);
|
||||
const [exportAccDialogOpen, setExportAccDialogOpen] = useState(false);
|
||||
const [exportAccDialogOpen, setExportAccDialogOpen] = useState(false);
|
||||
const [
|
||||
closeTokenAccountDialogOpen,
|
||||
setCloseTokenAccountDialogOpen,
|
||||
|
@ -665,7 +665,7 @@ function BalanceListItemDetails({
|
|||
onClick={() => setSendDialogOpen(true)}
|
||||
>
|
||||
Send
|
||||
</Button>
|
||||
</Button>
|
||||
{mint && amount === 0 ? (
|
||||
<Button
|
||||
variant="outlined"
|
||||
|
@ -705,7 +705,7 @@ function BalanceListItemDetails({
|
|||
onClose={() => setCloseTokenAccountDialogOpen(false)}
|
||||
balanceInfo={balanceInfo}
|
||||
publicKey={publicKey}
|
||||
/>
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import {
|
|||
import { parseTokenAccountData } from '../utils/tokens/data';
|
||||
import { Switch, Tooltip } from '@material-ui/core';
|
||||
import { EthFeeEstimate } from './EthFeeEstimate';
|
||||
import SwapWormholeDialog from './SwapWormholeDialog';
|
||||
|
||||
const WUSDC_MINT = new PublicKey(
|
||||
'BXXkv6z8ykpG1yuvUDPgh732wzVHB69RnB9YgSYh3itW',
|
||||
|
@ -43,12 +44,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();
|
||||
|
@ -65,43 +64,37 @@ export default function SendDialog({ open, onClose, publicKey, balanceInfo }) {
|
|||
const { mint, tokenName, tokenSymbol } = balanceInfo;
|
||||
|
||||
const getTabs = (mint) => {
|
||||
const wormholeTab = (
|
||||
<Tab label={'SPL Wormhole'} key="wormhole" value="wormhole" />
|
||||
);
|
||||
if (mint?.equals(WUSDC_MINT)) {
|
||||
return [
|
||||
<Tab label="SPL WUSDC" key="spl" value="spl" />,
|
||||
<Tab
|
||||
label="SPL USDC"
|
||||
key="wusdcToSplUsdc"
|
||||
value="wusdcToSplUsdc"
|
||||
/>,
|
||||
wormholeTab,
|
||||
<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"
|
||||
/>,
|
||||
wormholeTab,
|
||||
<Tab label="SPL USDT" key="wusdtToSplUsdt" value="wusdtToSplUsdt" />,
|
||||
<Tab label="ERC20 USDT" key="swap" value="swap" />,
|
||||
]
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
<Tab label={`SPL ${swapCoinInfo.ticker}`} key="spl" value="spl" />,
|
||||
wormholeTab,
|
||||
<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 (
|
||||
<>
|
||||
|
@ -109,6 +102,9 @@ export default function SendDialog({ open, onClose, publicKey, balanceInfo }) {
|
|||
open={open}
|
||||
onClose={onClose}
|
||||
onSubmit={() => onSubmitRef.current()}
|
||||
maxWidth={
|
||||
mint?.equals(WUSDC_MINT) || mint?.equals(WUSDT_MINT) ? 'md' : 'sm'
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<DialogTitle>
|
||||
|
@ -160,6 +156,14 @@ export default function SendDialog({ open, onClose, publicKey, balanceInfo }) {
|
|||
onSubmitRef={onSubmitRef}
|
||||
wusdtToSplUsdt
|
||||
/>
|
||||
) : tab === 'wormhole' ? (
|
||||
<SwapWormholeDialog
|
||||
publicKey={publicKey}
|
||||
onClose={onClose}
|
||||
balanceInfo={balanceInfo}
|
||||
swapCoinInfo={swapCoinInfo}
|
||||
onSubmitRef={onSubmitRef}
|
||||
/>
|
||||
) : (
|
||||
<SendSwapDialog
|
||||
key={tab}
|
||||
|
@ -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
|
||||
? 'sol'
|
||||
: swapCoinInfo.blockchain === 'sol'
|
||||
? 'eth'
|
||||
: swapCoinInfo.blockchain;
|
||||
const needMetamask = blockchain === 'eth';
|
||||
|
||||
const [ethBalance] = useAsyncData(
|
||||
|
@ -367,7 +372,13 @@ function SendSwapDialog({
|
|||
} else if (wusdtToSplUsdt && splUsdtWalletAddress) {
|
||||
setDestinationAddress(splUsdtWalletAddress);
|
||||
}
|
||||
}, [setDestinationAddress, wusdcToSplUsdc, splUsdcWalletAddress, wusdtToSplUsdt, splUsdtWalletAddress]);
|
||||
}, [
|
||||
setDestinationAddress,
|
||||
wusdcToSplUsdc,
|
||||
splUsdcWalletAddress,
|
||||
wusdtToSplUsdt,
|
||||
splUsdtWalletAddress,
|
||||
]);
|
||||
|
||||
async function makeTransaction() {
|
||||
let amount = Math.round(parseFloat(transferAmountString) * 10 ** decimals);
|
||||
|
@ -644,7 +655,7 @@ function useForm(
|
|||
};
|
||||
}
|
||||
|
||||
function balanceAmountToUserAmount(balanceAmount, decimals) {
|
||||
export function balanceAmountToUserAmount(balanceAmount, decimals) {
|
||||
return (balanceAmount / Math.pow(10, decimals)).toFixed(decimals);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,324 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import DialogActions from '@material-ui/core/DialogActions';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import DialogContent from '@material-ui/core/DialogContent';
|
||||
import DialogContentText from '@material-ui/core/DialogContentText';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import InputAdornment from '@material-ui/core/InputAdornment';
|
||||
import CircularProgress from '@material-ui/core/CircularProgress';
|
||||
import { PublicKey } from '@solana/web3.js';
|
||||
import { Pool } from '@project-serum/swap';
|
||||
import { balanceAmountToUserAmount } from './SendDialog';
|
||||
import { useWallet, useWalletAddressForMint } from '../utils/wallet';
|
||||
import { swapApiRequest } from '../utils/swap/api';
|
||||
import { getErc20Decimals } from '../utils/swap/eth.js';
|
||||
import { useSendTransaction } from '../utils/notifications';
|
||||
import { signAndSendTransaction } from '../utils/tokens';
|
||||
|
||||
const SWAP_PROGRAM_ID = new PublicKey(
|
||||
'SwaPpA9LAaLfeLi3a68M4DjnLqgtticKg6CnyNwgAC8',
|
||||
);
|
||||
const POOL_BASE = new PublicKey(
|
||||
'CAXLccDUeS6egtNNEBLrxAqxSvuL6SwspqYX14JdKaiK',
|
||||
);
|
||||
|
||||
export default function SwapWormholeDialog({
|
||||
publicKey,
|
||||
onClose,
|
||||
balanceInfo,
|
||||
swapCoinInfo,
|
||||
onSubmitRef,
|
||||
}) {
|
||||
// Possible values:
|
||||
//
|
||||
// * undefined => loading.
|
||||
// * pool.accountInfo === null => no pool exists.
|
||||
// * pool.accountInfo !== null => pool exists.
|
||||
const [pool, setPool] = useState(undefined);
|
||||
const [wormholeMintAddr, setWormholeMintAddr] = useState(null);
|
||||
const [transferAmountString, setTransferAmountString] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const wallet = useWallet();
|
||||
const [sendTransaction] = useSendTransaction();
|
||||
const { amount: balanceAmount, decimals, tokenSymbol } = balanceInfo;
|
||||
const parsedAmount = parseFloat(transferAmountString);
|
||||
const validAmount = parsedAmount > 0 && parsedAmount <= balanceAmount;
|
||||
const ethChainId = 2;
|
||||
const wormholeTokenAddr = useWalletAddressForMint(wormholeMintAddr);
|
||||
|
||||
// Note: there are three "useEffect" closures to be run in order.
|
||||
// Each one triggers the next.
|
||||
|
||||
// 1. Calculate wormhole wrapped token mint address *and*
|
||||
// url to initialize the AMM pool.
|
||||
useEffect(() => {
|
||||
if (wormholeMintAddr === null) {
|
||||
const fetch = async () => {
|
||||
let erc20Contract;
|
||||
let decimals;
|
||||
let _wormholeMintAddr;
|
||||
if (swapCoinInfo.ticker === 'ETH') {
|
||||
erc20Contract = 'eth';
|
||||
decimals = -1;
|
||||
_wormholeMintAddr = new PublicKey(
|
||||
'FeGn77dhg1KXRRFeSwwMiykZnZPw5JXW6naf2aQgZDQf',
|
||||
);
|
||||
} else if (swapCoinInfo.ticker === 'BTC') {
|
||||
erc20Contract = 'btc';
|
||||
decimals = -1;
|
||||
_wormholeMintAddr = new PublicKey(
|
||||
'qfnqNqs3nCAHjnyCgLRDbBtq4p2MtHZxw8YjSyYhPoL',
|
||||
);
|
||||
} else {
|
||||
erc20Contract = swapCoinInfo.erc20Contract;
|
||||
decimals = await getErc20Decimals(erc20Contract);
|
||||
_wormholeMintAddr = await wormholeMintAddress(
|
||||
ethChainId,
|
||||
Math.min(decimals, 9),
|
||||
Buffer.from(erc20Contract.slice(2), 'hex'),
|
||||
);
|
||||
}
|
||||
setWormholeMintAddr(_wormholeMintAddr);
|
||||
};
|
||||
fetch();
|
||||
}
|
||||
}, [
|
||||
ethChainId,
|
||||
swapCoinInfo.erc20Contract,
|
||||
swapCoinInfo.ticker,
|
||||
wormholeMintAddr,
|
||||
]);
|
||||
|
||||
// 2. Fetch the wormhole pool, if it exists.
|
||||
useEffect(() => {
|
||||
if (wormholeMintAddr !== null) {
|
||||
const fetch = async () => {
|
||||
const seed =
|
||||
balanceInfo.mint.toString().slice(0, 16) +
|
||||
wormholeMintAddr.toString().slice(0, 16);
|
||||
const publicKey = await PublicKey.createWithSeed(
|
||||
POOL_BASE,
|
||||
seed,
|
||||
SWAP_PROGRAM_ID,
|
||||
);
|
||||
const accountInfo = await wallet.connection.getAccountInfo(publicKey);
|
||||
setPool({
|
||||
publicKey,
|
||||
accountInfo,
|
||||
});
|
||||
};
|
||||
fetch();
|
||||
}
|
||||
}, [wormholeMintAddr, balanceInfo.mint, wallet.connection]);
|
||||
|
||||
// 3. Tell the bridge to create the AMM pool, if no
|
||||
// sollet <-> wormhole pool exists.
|
||||
useEffect(() => {
|
||||
if (
|
||||
pool &&
|
||||
pool.accountInfo === null &&
|
||||
pool.publicKey &&
|
||||
wormholeMintAddr &&
|
||||
balanceAmount > 0
|
||||
) {
|
||||
const url = `wormhole/pool/${
|
||||
swapCoinInfo.ticker
|
||||
}/${pool.publicKey.toString()}/${balanceInfo.mint.toString()}/${wormholeMintAddr.toString()}`;
|
||||
swapApiRequest('POST', url).catch(console.error);
|
||||
}
|
||||
}, [
|
||||
pool,
|
||||
wormholeMintAddr,
|
||||
balanceAmount,
|
||||
balanceInfo.mint,
|
||||
swapCoinInfo.ticker,
|
||||
]);
|
||||
|
||||
// Converts the sollet wrapped token into the wormhole wrapped token
|
||||
// by trading on the constant price pool.
|
||||
async function convert() {
|
||||
// User does not have a wormhole account. Make it.
|
||||
let _wormholeTokenAddr = wormholeTokenAddr;
|
||||
if (!_wormholeTokenAddr) {
|
||||
const createWormholeAccount = async () => {
|
||||
const [addr, txSig] = await wallet.createAssociatedTokenAccount(
|
||||
wormholeMintAddr,
|
||||
);
|
||||
_wormholeTokenAddr = addr;
|
||||
return txSig;
|
||||
};
|
||||
|
||||
let err = await new Promise((resolve) => {
|
||||
sendTransaction(createWormholeAccount(), {
|
||||
onSuccess: () => resolve(false),
|
||||
onError: () => resolve(true),
|
||||
});
|
||||
});
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Swapping from: sollet.
|
||||
const tokenIn = {
|
||||
mint: balanceInfo.mint,
|
||||
tokenAccount: publicKey,
|
||||
amount: parsedAmount,
|
||||
};
|
||||
// Swapping to: wormhole.
|
||||
const tokenOut = {
|
||||
mint: wormholeMintAddr,
|
||||
tokenAccount: _wormholeTokenAddr,
|
||||
amount: parsedAmount,
|
||||
};
|
||||
|
||||
// Misc swap params.
|
||||
const owner = wallet.publicKey;
|
||||
const slippage = 0.5;
|
||||
const hostFeeAccount = undefined;
|
||||
const skipPreflight = true;
|
||||
|
||||
// Constant price AMM client.
|
||||
const poolClient = await Pool.load(
|
||||
wallet.connection,
|
||||
pool.publicKey,
|
||||
SWAP_PROGRAM_ID,
|
||||
);
|
||||
// Execute swap.
|
||||
const { transaction, signers } = await poolClient.makeSwapTransaction(
|
||||
wallet.connection,
|
||||
owner,
|
||||
tokenIn,
|
||||
tokenOut,
|
||||
slippage,
|
||||
hostFeeAccount,
|
||||
);
|
||||
const txSig = await signAndSendTransaction(
|
||||
wallet.connection,
|
||||
transaction,
|
||||
wallet,
|
||||
signers,
|
||||
skipPreflight,
|
||||
);
|
||||
console.log('Transaction: ', txSig);
|
||||
return txSig;
|
||||
}
|
||||
async function onSubmit() {
|
||||
setIsLoading(true);
|
||||
await new Promise((resolve) => {
|
||||
sendTransaction(convert(), {
|
||||
onSuccess: () => resolve(),
|
||||
onError: () => resolve(),
|
||||
});
|
||||
});
|
||||
setIsLoading(false);
|
||||
}
|
||||
onSubmitRef.current = onSubmit;
|
||||
|
||||
return (
|
||||
<>
|
||||
<DialogContent style={{ paddingTop: 16 }}>
|
||||
{pool === undefined || isLoading ? (
|
||||
<CircularProgress
|
||||
style={{
|
||||
display: 'block',
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
}}
|
||||
/>
|
||||
) : pool.accountInfo === null ? (
|
||||
<DialogContentText>
|
||||
{`Wormhole conversion is not yet setup for this token. Please try later.`}
|
||||
</DialogContentText>
|
||||
) : (
|
||||
<>
|
||||
<DialogContentText>
|
||||
{`Convert your tokens into wormhole-wrapped tokens.`}
|
||||
</DialogContentText>
|
||||
<TextField
|
||||
label="Amount"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
margin="normal"
|
||||
type="number"
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<Button
|
||||
onClick={() =>
|
||||
setTransferAmountString(
|
||||
balanceAmountToUserAmount(balanceAmount, decimals),
|
||||
)
|
||||
}
|
||||
>
|
||||
MAX
|
||||
</Button>
|
||||
{tokenSymbol ? tokenSymbol : null}
|
||||
</InputAdornment>
|
||||
),
|
||||
inputProps: {
|
||||
step: Math.pow(10, -decimals),
|
||||
},
|
||||
}}
|
||||
value={transferAmountString}
|
||||
onChange={(e) => setTransferAmountString(e.target.value.trim())}
|
||||
helperText={
|
||||
<span
|
||||
onClick={() =>
|
||||
setTransferAmountString(
|
||||
balanceAmountToUserAmount(balanceAmount, decimals),
|
||||
)
|
||||
}
|
||||
>
|
||||
Max: {balanceAmountToUserAmount(balanceAmount, decimals)}
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onClose}>Cancel</Button>
|
||||
<Button disabled={!validAmount} type="submit" color="primary">
|
||||
Convert
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// Currently, only used for calculating the Solana wrapped token mint address.
|
||||
// I.e. assetChain is always === 2 and assetAddress always is the ethereum
|
||||
// contract address.
|
||||
async function wormholeMintAddress(
|
||||
assetChain: number,
|
||||
assetDecimals: number,
|
||||
assetAddress: Buffer,
|
||||
): PublicKey {
|
||||
const bridgeId = new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC');
|
||||
const bridgeAuthority = await getBridgeAuthority(bridgeId);
|
||||
const seeds = [
|
||||
Buffer.from('wrapped'),
|
||||
bridgeAuthority.toBuffer(),
|
||||
Buffer.of(assetChain),
|
||||
Buffer.of(assetDecimals),
|
||||
padBuffer(assetAddress, 32),
|
||||
];
|
||||
|
||||
const [mint] = await PublicKey.findProgramAddress(seeds, bridgeId);
|
||||
|
||||
return mint;
|
||||
}
|
||||
|
||||
async function getBridgeAuthority(bridgeId: PublicKey): PublicKey {
|
||||
const [ba] = await PublicKey.findProgramAddress(
|
||||
[Buffer.from('bridge')],
|
||||
bridgeId,
|
||||
);
|
||||
return ba;
|
||||
}
|
||||
|
||||
export function padBuffer(b: Buffer, len: number): Buffer {
|
||||
const zeroPad = Buffer.alloc(len);
|
||||
b.copy(zeroPad, len - b.length);
|
||||
return zeroPad;
|
||||
}
|
|
@ -27,6 +27,12 @@ export function useEthAccount() {
|
|||
return account;
|
||||
}
|
||||
|
||||
export async function getErc20Decimals(erc20Address) {
|
||||
const erc20 = new web3.eth.Contract(ERC20_ABI, erc20Address);
|
||||
const decimals = await erc20.methods.decimals().call();
|
||||
return decimals;
|
||||
}
|
||||
|
||||
export async function getErc20Balance(account, erc20Address) {
|
||||
if (!erc20Address) {
|
||||
return parseInt(await web3.eth.getBalance(account)) / 1e18;
|
||||
|
|
115
yarn.lock
115
yarn.lock
|
@ -1254,6 +1254,13 @@
|
|||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.10.5":
|
||||
version "7.13.10"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d"
|
||||
integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.12.5", "@babel/runtime@^7.9.2":
|
||||
version "7.12.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e"
|
||||
|
@ -1862,7 +1869,7 @@
|
|||
schema-utils "^2.6.5"
|
||||
source-map "^0.7.3"
|
||||
|
||||
"@project-serum/serum@^0.13.33":
|
||||
"@project-serum/serum@^0.13.21", "@project-serum/serum@^0.13.33":
|
||||
version "0.13.33"
|
||||
resolved "https://registry.yarnpkg.com/@project-serum/serum/-/serum-0.13.33.tgz#03ce8219c1bb458f56c09dc8aa621d76538e70f5"
|
||||
integrity sha512-g2ztZwhQAvhGE9u4/Md6uEFBpaOMV2Xa/H/FGhgTx3iBv2sikW5fheHRJ8Vy7yEA9ZhZCuzbCkw8Wz1fq82VAg==
|
||||
|
@ -1871,6 +1878,19 @@
|
|||
bn.js "^5.1.2"
|
||||
buffer-layout "^1.2.0"
|
||||
|
||||
"@project-serum/swap@^0.0.11":
|
||||
version "0.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@project-serum/swap/-/swap-0.0.11.tgz#f606b73fbdcd152d7835068f168cb8ad172d8414"
|
||||
integrity sha512-DxvNL81LnBcE62oENr0LOqIAen9/LNb7gEcDbNlIHr02PckUCZTDIngIsbDY09ld1+V7STy+pLPnstt6ZZElsg==
|
||||
dependencies:
|
||||
"@project-serum/serum" "^0.13.21"
|
||||
"@solana/spl-token" "^0.0.13"
|
||||
"@solana/spl-token-swap" "0.1.0"
|
||||
bn.js "^5.1.3"
|
||||
bs58 "^4.0.1"
|
||||
buffer-layout "^1.2.0"
|
||||
dotenv "^8.2.0"
|
||||
|
||||
"@rollup/plugin-node-resolve@^7.1.1":
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz#80de384edfbd7bfc9101164910f86078151a3eca"
|
||||
|
@ -1925,6 +1945,54 @@
|
|||
dependencies:
|
||||
cross-fetch "^3.0.6"
|
||||
|
||||
"@solana/spl-token-swap@0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@solana/spl-token-swap/-/spl-token-swap-0.1.0.tgz#a1bc2b0c96edae8b31bb2cc000ebacdc36e131c8"
|
||||
integrity sha512-h0ntp6xwRZBEKDd6oNhJTbPISjIfeGm0eqQqAccTkeluo1zHve4dnUChTKF4MQ+JqXjfqd6z6DJjfa0+dGA37w==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.11.2"
|
||||
"@solana/web3.js" "^0.90.0"
|
||||
bn.js "^5.1.3"
|
||||
buffer-layout "^1.2.0"
|
||||
dotenv "8.2.0"
|
||||
json-to-pretty-yaml "^1.2.2"
|
||||
mkdirp "1.0.4"
|
||||
|
||||
"@solana/spl-token@^0.0.13":
|
||||
version "0.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.0.13.tgz#5e0b235b1f8b34643280401dbfddeb34d13d1acd"
|
||||
integrity sha512-WT8M9V/hxURR5jLbhr3zgwVsgcY6m8UhHtK045w7o+jx8FJ9MKARkj387WBFU7mKiFq0k8jw/8YL7XmnIUuH8Q==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.10.5"
|
||||
"@solana/web3.js" "^0.86.1"
|
||||
bn.js "^5.0.0"
|
||||
buffer-layout "^1.2.0"
|
||||
dotenv "8.2.0"
|
||||
mkdirp "1.0.4"
|
||||
|
||||
"@solana/web3.js@^0.86.1":
|
||||
version "0.86.4"
|
||||
resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-0.86.4.tgz#69216d3928ca4727c25a1ea96c405e897156ac3b"
|
||||
integrity sha512-FpabDmdyxBN5aHIVUWc9Q6pXJFWiLRm/xeyxFg9O9ICHjiUkd38omds7G0CAmykIccG7zaMziwtkXp+0KvQOhA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.3.1"
|
||||
bn.js "^5.0.0"
|
||||
bs58 "^4.0.1"
|
||||
buffer "^5.4.3"
|
||||
buffer-layout "^1.2.0"
|
||||
crypto-hash "^1.2.2"
|
||||
esdoc-inject-style-plugin "^1.0.0"
|
||||
jayson "^3.0.1"
|
||||
keccak "^3.0.1"
|
||||
mz "^2.7.0"
|
||||
node-fetch "^2.2.0"
|
||||
npm-run-all "^4.1.5"
|
||||
rpc-websockets "^7.4.2"
|
||||
secp256k1 "^4.0.2"
|
||||
superstruct "^0.8.3"
|
||||
tweetnacl "^1.0.0"
|
||||
ws "^7.0.0"
|
||||
|
||||
"@solana/web3.js@^0.87.2":
|
||||
version "0.87.2"
|
||||
resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-0.87.2.tgz#92c8d344695c6113d4e0eb3339117fbc6b22d0d2"
|
||||
|
@ -3477,6 +3545,11 @@ bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2:
|
|||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b"
|
||||
integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==
|
||||
|
||||
bn.js@^5.1.3:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002"
|
||||
integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==
|
||||
|
||||
body-parser@1.19.0, body-parser@^1.16.0:
|
||||
version "1.19.0"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
|
||||
|
@ -3708,6 +3781,14 @@ buffer@^5.0.5, buffer@^5.5.0, buffer@^5.6.0:
|
|||
base64-js "^1.0.2"
|
||||
ieee754 "^1.1.4"
|
||||
|
||||
buffer@^5.4.3:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
|
||||
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
|
||||
dependencies:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
buffer@^6.0.1:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
|
||||
|
@ -5146,7 +5227,7 @@ dotenv-expand@5.1.0:
|
|||
resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0"
|
||||
integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==
|
||||
|
||||
dotenv@8.2.0:
|
||||
dotenv@8.2.0, dotenv@^8.2.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
|
||||
integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==
|
||||
|
@ -6985,16 +7066,16 @@ idna-uts46-hx@^2.3.1:
|
|||
dependencies:
|
||||
punycode "2.1.0"
|
||||
|
||||
ieee754@^1.1.13, ieee754@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||
|
||||
ieee754@^1.1.4:
|
||||
version "1.1.13"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"
|
||||
integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==
|
||||
|
||||
ieee754@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||
|
||||
iferr@^0.1.5:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
|
||||
|
@ -8140,6 +8221,14 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
|
|||
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
|
||||
|
||||
json-to-pretty-yaml@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz#f4cd0bd0a5e8fe1df25aaf5ba118b099fd992d5b"
|
||||
integrity sha1-9M0L0KXo/h3yWq9boRiwmf2ZLVs=
|
||||
dependencies:
|
||||
remedial "^1.0.7"
|
||||
remove-trailing-spaces "^1.0.6"
|
||||
|
||||
json3@^3.3.2:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81"
|
||||
|
@ -8916,7 +9005,7 @@ mkdirp-promise@^5.0.1:
|
|||
dependencies:
|
||||
mkdirp "*"
|
||||
|
||||
mkdirp@*, mkdirp@^1.0.3, mkdirp@^1.0.4:
|
||||
mkdirp@*, mkdirp@1.0.4, mkdirp@^1.0.3, mkdirp@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
@ -11196,11 +11285,21 @@ relateurl@^0.2.7:
|
|||
resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
|
||||
integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=
|
||||
|
||||
remedial@^1.0.7:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/remedial/-/remedial-1.0.8.tgz#a5e4fd52a0e4956adbaf62da63a5a46a78c578a0"
|
||||
integrity sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==
|
||||
|
||||
remove-trailing-separator@^1.0.1:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
|
||||
integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8=
|
||||
|
||||
remove-trailing-spaces@^1.0.6:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz#4354d22f3236374702f58ee373168f6d6887ada7"
|
||||
integrity sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA==
|
||||
|
||||
renderkid@^2.0.1:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.3.tgz#380179c2ff5ae1365c522bf2fcfcff01c5b74149"
|
||||
|
|
Loading…
Reference in New Issue