Merge remote-tracking branch 'origin/main' into feature/m

This commit is contained in:
bartosz-lipinski 2021-04-30 19:31:56 -05:00
commit 3347e30111
8 changed files with 158 additions and 99 deletions

View File

@ -22,6 +22,7 @@
"@solana/wallet-base": "0.0.1",
"@solana/wallet-ledger": "0.0.1",
"@solana/web3.js": "^1.5.0",
"bignumber.js": "^9.0.1",
"bn.js": "^5.1.3",
"bs58": "^4.0.1",
"buffer-layout": "1.2.0",

View File

@ -1,4 +1,5 @@
import { BigNumber } from 'ethers/utils';
import { BigNumber } from 'bignumber.js';
import {ethers} from "ethers";
import { ASSET_CHAIN } from '../constants';
export interface ProgressUpdate {
@ -14,7 +15,7 @@ export interface TransferRequestInfo {
name: string;
balance: BigNumber;
decimals: number;
allowance: BigNumber;
allowance: ethers.utils.BigNumber;
isWrapped: boolean;
chainID: number;
assetAddress: Buffer;

View File

@ -21,6 +21,7 @@ import {
import { AccountInfo } from '@solana/spl-token';
import { TransferRequest, ProgressUpdate } from './interface';
import { WalletAdapter } from '@solana/wallet-base';
import { BigNumber } from "bignumber.js";
export const toSolana = async (
connection: Connection,
@ -39,6 +40,9 @@ export const toSolana = async (
signer.getAddress(),
'pending',
);
const amountBigNumber = new BigNumber(request.amount.toString()).toFormat(
request.info.decimals,
);
const amountBN = ethers.utils.parseUnits(
request.amount.toString(),

View File

@ -38,6 +38,7 @@
"@web3-react/walletlink-connector": "^6.0.9",
"@welldone-software/why-did-you-render": "^6.0.5",
"animejs": "^3.2.1",
"bignumber.js": "^9.0.1",
"bn.js": "^5.1.3",
"bs58": "^4.0.1",
"buffer-layout": "^1.2.0",

View File

@ -40,7 +40,7 @@ export function Input(props: {
props.onInputChange && props.onInputChange(props.balance)
}
>
{props.balance}
{props.balance?.toFixed(6)}
</div>
</div>
<div className="input-container">

View File

@ -20,8 +20,8 @@ import {
filterModalSolTokens,
} from '../utils/assets';
import { useEthereum } from './ethereum';
import { BigNumber } from 'ethers/utils';
import { WrappedAssetFactory } from '@solana/bridge-sdk';
import { BigNumber } from 'bignumber.js';
import { AssetMeta, WrappedAssetFactory } from '@solana/bridge-sdk';
import { WormholeFactory } from '@solana/bridge-sdk';
import {
bridgeAuthorityKey,
@ -30,6 +30,7 @@ import {
} from '@solana/bridge-sdk';
import { useBridge } from './bridge';
import { PublicKey } from '@solana/web3.js';
import { ethers } from 'ethers';
export interface TokenChainContextState {
info?: TransferRequestInfo;
@ -108,7 +109,7 @@ export const useCurrencyLeg = (mintAddress: string) => {
name: '',
balance: new BigNumber(0),
decimals: 0,
allowance: new BigNumber(0),
allowance: new ethers.utils.BigNumber(0),
isWrapped: false,
chainID: 0,
assetAddress: new Buffer(0),
@ -121,43 +122,69 @@ export const useCurrencyLeg = (mintAddress: string) => {
(async () => {
const ethToken = ethTokens.find(t => t.address === mintAddress);
const solToken = solTokens.find(t => t.address === mintAddress);
let solToken = solTokens.find(t => t.address === mintAddress);
let mintKeyAddress = '';
let symbol = '';
let decimals = 0;
// eth assets on eth chain
// eth asset on sol chain
// sol asset on eth chain
// sol asset on sol chain
//let ethAddress: string = '';
// console.log({ chain, solToken, ethToken });
//console.log({ chain, solToken, ethToken });
if (chain === ASSET_CHAIN.Solana) {
if (!solToken) {
if (!solToken && ethToken) {
try {
const bridgeId = programIds().wormhole.pubkey;
const authority = await bridgeAuthorityKey(bridgeId);
const assetAddress = Buffer.from(ethToken.address.slice(2), 'hex');
const meta: AssetMeta = {
decimals: Math.min(ethToken.decimals, 9),
address: assetAddress,
chain: ASSET_CHAIN.Ethereum,
};
const mintKey = await wrappedAssetMintKey(
bridgeId,
authority,
meta,
);
if (mintKey) {
mintKeyAddress = mintKey.toBase58();
solToken = solTokens.find(t => t.address === mintKeyAddress);
if (!solToken) {
symbol = ethToken.symbol;
decimals = ethToken.decimals;
}
} else {
setInfo(defaultCoinInfo);
return;
}
} catch {
setInfo(defaultCoinInfo);
return;
}
}
if (!solToken && (!symbol || !mintKeyAddress || !decimals)) {
setInfo(defaultCoinInfo);
return;
}
// TODO: checked if mint is wrapped mint from eth...
const currentAccount = userAccounts?.find(
a => a.info.mint.toBase58() === solToken.address,
a => a.info.mint.toBase58() === (solToken?.address || mintKeyAddress),
);
const assetMeta = await bridge?.fetchAssetMeta(
new PublicKey(solToken.address),
new PublicKey(solToken?.address || mintKeyAddress),
);
if (!assetMeta || !currentAccount) {
setInfo(defaultCoinInfo);
return;
}
let info = {
address: currentAccount.pubkey.toBase58(),
name: solToken.symbol,
name: solToken?.symbol || symbol,
balance: new BigNumber(currentAccount?.info.amount.toNumber() || 0),
allowance: new BigNumber(0),
decimals: solToken.decimals,
allowance: new ethers.utils.BigNumber(0),
decimals: solToken?.decimals || decimals,
isWrapped: assetMeta.chain != ASSET_CHAIN.Solana,
chainID: assetMeta.chain,
assetAddress: assetMeta.address,
mint: solToken.address,
mint: solToken?.address || mintKeyAddress,
};
setInfo(info);
}
@ -197,7 +224,9 @@ export const useCurrencyLeg = (mintAddress: string) => {
}
if (chain === ASSET_CHAIN.Ethereum) {
info.balance = await e.balanceOf(addr);
info.balance = new BigNumber(
new ethers.utils.BigNumber(await e.balanceOf(addr)).toString(),
);
} else {
// TODO: get balance on other chains for assets that came from eth
@ -211,7 +240,7 @@ export const useCurrencyLeg = (mintAddress: string) => {
});
}
// console.log({ info });
//console.log({ info });
setInfo(info);
}
})();

View File

@ -5,6 +5,7 @@ import {
programIds,
notify,
useWallet,
ParsedAccountBase,
} from '@oyster/common';
import {
WORMHOLE_PROGRAM_ID,
@ -29,11 +30,12 @@ import {
COINGECKO_POOL_INTERVAL,
useCoingecko,
} from '../contexts/coingecko';
import { BN } from 'bn.js';
import { BigNumber } from 'bignumber.js';
import { WormholeFactory } from '@solana/bridge-sdk';
import { ethers } from 'ethers';
import { useBridge } from '../contexts/bridge';
import { SolanaBridge } from '@solana/bridge-sdk';
import BN from 'bn.js';
type WrappedTransferMeta = {
chain: number;
@ -47,7 +49,7 @@ type WrappedTransferMeta = {
symbol?: string;
amount: number;
value?: number | string;
txhash?: string;
txhash: string;
date: number; // timestamp
status?: string;
owner?: string;
@ -55,6 +57,8 @@ type WrappedTransferMeta = {
vaa?: any;
};
const transferCache = new Map<string, WrappedTransferMeta>();
const queryWrappedMetaTransactions = async (
authorityKey: PublicKey,
connection: Connection,
@ -101,14 +105,16 @@ const queryWrappedMetaTransactions = async (
assetAddress = new PublicKey(metaTransfer.assetAddress).toBase58();
}
const dec = new BN(10).pow(new BN(metaTransfer.assetDecimals));
const rawAmount = new BN(metaTransfer.amount, 2, 'le');
const div = rawAmount.div(dec).toNumber();
const mod = rawAmount.mod(dec).toNumber();
const amount = parseFloat(div + '.' + mod.toString());
const dec = new BigNumber(10).pow(
new BigNumber(metaTransfer.assetDecimals),
);
const rawAmount = new BigNumber(
new BN(metaTransfer.amount, 2, 'le').toString(),
);
const amount = rawAmount.div(dec).toNumber();
const txhash = acc.publicKey.toBase58();
transfers.set(assetAddress, {
transfers.set(txhash, {
publicKey: acc.publicKey,
amount,
date: metaTransfer.vaaTime,
@ -125,81 +131,97 @@ const queryWrappedMetaTransactions = async (
await Promise.all(
[...transfers.values()].map(async transfer => {
const resp = await (connection as any)._rpcRequest(
'getConfirmedSignaturesForAddress2',
[transfer.publicKey.toBase58()],
);
for (const sig of resp.result) {
const confirmedTx = await connection.getParsedConfirmedTransaction(
sig.signature,
'finalized',
const cachedTransfer = transferCache.get(transfer.txhash);
if (cachedTransfer && cachedTransfer.status === 'Completed') {
transfer.vaa = cachedTransfer.vaa;
transfer.status = cachedTransfer.status;
transfer.owner = cachedTransfer.owner;
} else {
const resp = await (connection as any)._rpcRequest(
'getConfirmedSignaturesForAddress2',
[transfer.publicKey.toBase58()],
);
if (!confirmedTx) continue;
const instructions = confirmedTx.transaction?.message?.instructions;
const filteredInstructions = instructions?.filter(ins => {
return ins.programId.toBase58() === WORMHOLE_PROGRAM_ID.toBase58();
});
if (filteredInstructions && filteredInstructions?.length > 0) {
for (const ins of filteredInstructions) {
const data = bs58.decode((ins as PartiallyDecodedInstruction).data);
if (data[0] === TRANSFER_ASSETS_OUT_INSTRUCTION) {
try {
transfer.owner = (ins as PartiallyDecodedInstruction).accounts[10].toBase58();
} catch {
// Catch no owner
transfer.owner = '';
}
}
if (
data[0] === POSTVAA_INSTRUCTION &&
confirmedTx.meta?.err == null &&
bridge
) {
const lockup = transfer.lockup;
let vaa = lockup.vaa;
for (let i = vaa.length; i > 0; i--) {
if (vaa[i] == 0xff) {
vaa = vaa.slice(0, i);
break;
for (const sig of resp.result) {
const confirmedTx = await connection.getParsedConfirmedTransaction(
sig.signature,
'finalized',
);
if (!confirmedTx) continue;
const instructions = confirmedTx.transaction?.message?.instructions;
const filteredInstructions = instructions?.filter(ins => {
return ins.programId.toBase58() === WORMHOLE_PROGRAM_ID.toBase58();
});
if (filteredInstructions && filteredInstructions?.length > 0) {
for (const ins of filteredInstructions) {
const data = bs58.decode(
(ins as PartiallyDecodedInstruction).data,
);
if (data[0] === TRANSFER_ASSETS_OUT_INSTRUCTION) {
try {
transfer.owner = (ins as PartiallyDecodedInstruction).accounts[10].toBase58();
} catch {
// Catch no owner
transfer.owner = '';
}
}
let signatures = await bridge.fetchSignatureStatus(
lockup.signatureAccount,
);
let sigData = Buffer.of(
...signatures.reduce((previousValue, currentValue) => {
previousValue.push(currentValue.index);
previousValue.push(...currentValue.signature);
return previousValue;
}, new Array<number>()),
);
if (
data[0] === POSTVAA_INSTRUCTION &&
confirmedTx.meta?.err == null &&
bridge
) {
const lockup = transfer.lockup;
let vaa = lockup.vaa;
for (let i = vaa.length; i > 0; i--) {
if (vaa[i] == 0xff) {
vaa = vaa.slice(0, i);
break;
}
}
try {
let signatures = await bridge.fetchSignatureStatus(
lockup.signatureAccount,
);
let sigData = Buffer.of(
...signatures.reduce((previousValue, currentValue) => {
previousValue.push(currentValue.index);
previousValue.push(...currentValue.signature);
vaa = Buffer.concat([
vaa.slice(0, 5),
Buffer.of(signatures.length),
sigData,
vaa.slice(6),
]);
try {
if (vaa?.length) {
const _ = await wh.parseAndVerifyVAA(vaa);
transfer.status = 'Failed';
transfer.vaa = vaa;
//TODO: handle vaa not posted
//console.log({ result });
} else {
return previousValue;
}, new Array<number>()),
);
vaa = Buffer.concat([
vaa.slice(0, 5),
Buffer.of(signatures.length),
sigData,
vaa.slice(6),
]);
try {
if (vaa?.length) {
const _ = await wh.parseAndVerifyVAA(vaa);
transfer.status = 'Failed';
transfer.vaa = vaa;
//TODO: handle vaa not posted
//console.log({ result });
} else {
transfer.status = 'Error';
transfer.vaa = vaa;
//TODO: handle empty data
//console.log({ vaa });
}
} catch (e) {
//console.log({ error: e });
transfer.vaa = vaa;
transfer.status = 'Completed';
transferCache.set(transfer.txhash, transfer);
}
} catch (e) {
transfer.status = 'Error';
transfer.vaa = vaa;
//TODO: handle empty data
//console.log({ vaa });
//TODO: handle error
}
} catch (e) {
//console.log({ error: e });
transfer.vaa = vaa;
transfer.status = 'Completed';
}
}
}

View File

@ -40,6 +40,7 @@
"@types/react-router-dom": "^5.1.6",
"@welldone-software/why-did-you-render": "^6.0.5",
"antd": "^4.6.6",
"bignumber.js": "^9.0.1",
"bn.js": "^5.1.3",
"borsh": "^0.3.1",
"bs58": "^4.0.1",