feat: to solana

This commit is contained in:
bartosz-lipinski 2021-03-12 16:20:22 -06:00
parent 85d3f8aaf4
commit 3db159667d
6 changed files with 128 additions and 104 deletions

View File

@ -33,7 +33,7 @@ export const AppLayout = React.memo((props: any) => {
<Wormhole <Wormhole
onCreated={() => setWormholeReady(true)} onCreated={() => setWormholeReady(true)}
show={true} show={true}
rotate={isRoot} rotate={true}
> >
<Layout title={LABELS.APP_TITLE}> <Layout title={LABELS.APP_TITLE}>
{isRoot && ( {isRoot && (

View File

@ -47,7 +47,7 @@ const WormholeGeometry = ({ rotate }: { rotate?: boolean }) => {
if (mesh.current) { if (mesh.current) {
// x-Axis defines the "top" we're looking at, try e.g. 30.5 // x-Axis defines the "top" we're looking at, try e.g. 30.5
mesh.current.rotation.x = 30; mesh.current.rotation.x = 30;
if (!rotate) { if (rotate) {
mesh.current.rotation.z += 0.0005; mesh.current.rotation.z += 0.0005;
} }
} }

View File

@ -37,20 +37,28 @@ export const fromSolana = async (
provider: ethers.providers.Web3Provider, provider: ethers.providers.Web3Provider,
setProgress: (update: ProgressUpdate) => void, setProgress: (update: ProgressUpdate) => void,
) => { ) => {
if (!request.asset) { if (
!request.asset ||
!request.amount ||
!request.recipient ||
!request.toChain ||
!request.info
) {
return; return;
} }
const walletName = 'MetaMask'; const walletName = 'MetaMask';
request.signer = provider?.getSigner(); const signer = provider?.getSigner();
request.recipient = Buffer.from( request.recipient = Buffer.from((await signer.getAddress()).slice(2), 'hex');
(await request.signer.getAddress()).slice(2), const nonce = await provider.getTransactionCount(
'hex', signer.getAddress(),
);
request.nonce = await provider.getTransactionCount(
request.signer.getAddress(),
'pending', 'pending',
); );
request.amountBN = ethers.utils.parseUnits(
request.amount.toString(),
request.info.decimals,
);
let counter = 0; let counter = 0;
// check difference between lock/approve (invoke lock if allowance < amount) // check difference between lock/approve (invoke lock if allowance < amount)
const steps = { const steps = {
@ -63,11 +71,6 @@ export const fromSolana = async (
throw new Error('Missing amount'); throw new Error('Missing amount');
} }
request.amountBN = ethers.utils.parseUnits(
request.amount.toString(),
request.info.decimals,
);
return steps.lock(request); return steps.lock(request);
}, },
@ -138,75 +141,108 @@ export const fromSolana = async (
proposalKey: PublicKey, proposalKey: PublicKey,
slot: number, slot: number,
) => { ) => {
let completed = false; return new Promise<void>((resolve, reject) => {
let startSlot = slot; let completed = false;
let startSlot = slot;
let group = 'Lock assets'; let group = 'Lock assets';
let slotUpdateListener = connection.onSlotChange(slot => { let slotUpdateListener = connection.onSlotChange(slot => {
if (completed) return;
const passedSlots = slot.slot - startSlot;
const isLast = passedSlots - 1 === 31;
if (passedSlots < 32) {
// setLoading({
// loading: true,
// message: "Awaiting confirmations",
// progress: {
// completion: (slot.slot - startSlot) / 32 * 100,
// content: `${slot.slot - startSlot}/${32}`
// }
// })
// setProgress({
// message: ethConfirmationMessage(passedBlocks),
// type: isLast ? 'done' : 'wait',
// step: counter++,
// group,
// replace: passedBlocks > 0,
// });
} else {
//setLoading({loading: true, message: "Awaiting guardian confirmation"})
}
});
let accountChangeListener = connection.onAccountChange(
proposalKey,
async a => {
if (completed) return; if (completed) return;
const passedSlots = slot.slot - startSlot;
const isLast = passedSlots - 1 === 31;
if (passedSlots < 32) {
// setLoading({
// loading: true,
// message: "Awaiting confirmations",
// progress: {
// completion: (slot.slot - startSlot) / 32 * 100,
// content: `${slot.slot - startSlot}/${32}`
// }
// })
// setProgress({
// message: ethConfirmationMessage(passedBlocks),
// type: isLast ? 'done' : 'wait',
// step: counter++,
// group,
// replace: passedBlocks > 0,
// });
} else {
//setLoading({loading: true, message: "Awaiting guardian confirmation"})
}
});
let lockup = TransferOutProposalLayout.decode(a.data); let accountChangeListener = connection.onAccountChange(
let vaa = lockup.vaa; proposalKey,
async a => {
if (completed) return;
for (let i = vaa.length; i > 0; i--) { let lockup = TransferOutProposalLayout.decode(a.data);
if (vaa[i] == 0xff) { let vaa = lockup.vaa;
vaa = vaa.slice(0, i);
break; for (let i = vaa.length; i > 0; i--) {
if (vaa[i] == 0xff) {
vaa = vaa.slice(0, i);
break;
}
} }
}
// Probably a poke // Probably a poke
if (vaa.filter((v: number) => v !== 0).length == 0) { if (vaa.filter((v: number) => v !== 0).length == 0) {
return; return;
} }
completed = true; completed = true;
connection.removeAccountChangeListener(accountChangeListener); connection.removeAccountChangeListener(accountChangeListener);
connection.removeSlotChangeListener(slotUpdateListener); connection.removeSlotChangeListener(slotUpdateListener);
// let signatures = await bridge.fetchSignatureStatus(lockup.signatureAccount); let signatures = await bridge.fetchSignatureStatus(
// let sigData = Buffer.of(...signatures.reduce((previousValue, currentValue) => { lockup.signatureAccount,
// previousValue.push(currentValue.index) );
// previousValue.push(...currentValue.signature) let sigData = Buffer.of(
...signatures.reduce((previousValue, currentValue) => {
previousValue.push(currentValue.index);
previousValue.push(...currentValue.signature);
// return previousValue return previousValue;
// }, new Array<number>())) }, new Array<number>()),
);
// vaa = Buffer.concat([vaa.slice(0, 5), Buffer.of(signatures.length), sigData, vaa.slice(6)]) vaa = Buffer.concat([
// transferVAA = vaa vaa.slice(0, 5),
}, Buffer.of(signatures.length),
'single', sigData,
); vaa.slice(6),
]);
// transferVAA = vaa
try {
await steps.postVAA(request);
resolve();
} catch {
reject();
}
},
'single',
);
});
},
postVAA: async (request: TransferRequest) => {
let wh = WormholeFactory.connect(programIds().wormhole.bridge, signer);
// setLoading({
// ...loading,
// loading: true,
// message: "Sign the claim...",
// })
let tx = await wh.submitVAA(vaa);
// setLoading({
// ...loading,
// loading: true,
// message: "Waiting for tokens unlock to be mined...",
// })
await tx.wait(1);
// message.success({content: "Execution of VAA succeeded", key: "eth_tx"})
}, },
postVAA: async (request: TransferRequest) => {},
}; };
return steps.transfer(request); return steps.transfer(request);

View File

@ -24,11 +24,6 @@ export interface TransferRequestInfo {
} }
export interface TransferRequest { export interface TransferRequest {
// ethereum specific fields, TODO: remove
nonce?: number;
signer?: ethers.Signer;
amountBN?: BigNumber;
amount?: number; amount?: number;
info?: TransferRequestInfo; info?: TransferRequestInfo;

View File

@ -30,17 +30,22 @@ export const toSolana = async (
provider: ethers.providers.Web3Provider, provider: ethers.providers.Web3Provider,
setProgress: (update: ProgressUpdate) => void, setProgress: (update: ProgressUpdate) => void,
) => { ) => {
if (!request.asset) { if (!request.asset || !request.amount || !request.info) {
return; return;
} }
const walletName = 'MetaMask'; const walletName = 'MetaMask';
request.signer = provider?.getSigner(); const signer = provider?.getSigner();
request.nonce = await provider.getTransactionCount( const nonce = await provider.getTransactionCount(
request.signer.getAddress(), signer.getAddress(),
'pending', 'pending',
); );
const amountBN = ethers.utils.parseUnits(
request.amount.toString(),
request.info.decimals,
);
let counter = 0; let counter = 0;
// check difference between lock/approve (invoke lock if allowance < amount) // check difference between lock/approve (invoke lock if allowance < amount)
const steps = { const steps = {
@ -49,11 +54,6 @@ export const toSolana = async (
return; return;
} }
request.amountBN = ethers.utils.parseUnits(
request.amount.toString(),
request.info.decimals,
);
return steps.prepare(request); return steps.prepare(request);
}, },
@ -162,24 +162,21 @@ export const toSolana = async (
}, },
// approves assets for transfer // approves assets for transfer
approve: async (request: TransferRequest) => { approve: async (request: TransferRequest) => {
if (!request.amountBN || !request.asset || !request.signer) { if (!request.asset) {
return; return;
} }
const group = 'Approve assets'; const group = 'Approve assets';
try { try {
if (request.info?.allowance.lt(request.amountBN)) { if (request.info?.allowance.lt(amountBN)) {
let e = Erc20Factory.connect(request.asset, request.signer); let e = Erc20Factory.connect(request.asset, signer);
setProgress({ setProgress({
message: `Waiting for ${walletName} approval`, message: `Waiting for ${walletName} approval`,
type: 'user', type: 'user',
group, group,
step: counter++, step: counter++,
}); });
let res = await e.approve( let res = await e.approve(programIds().wormhole.bridge, amountBN);
programIds().wormhole.bridge,
request.amountBN,
);
setProgress({ setProgress({
message: 'Waiting for ETH transaction to be mined...', message: 'Waiting for ETH transaction to be mined...',
type: 'wait', type: 'wait',
@ -216,13 +213,11 @@ export const toSolana = async (
// locks assets in the bridge // locks assets in the bridge
lock: async (request: TransferRequest) => { lock: async (request: TransferRequest) => {
if ( if (
!request.amountBN || !amountBN ||
!request.asset || !request.asset ||
!request.signer ||
!request.recipient || !request.recipient ||
!request.toChain || !request.toChain ||
!request.info || !request.info
!request.nonce
) { ) {
return; return;
} }
@ -230,10 +225,7 @@ export const toSolana = async (
let group = 'Lock assets'; let group = 'Lock assets';
try { try {
let wh = WormholeFactory.connect( let wh = WormholeFactory.connect(programIds().wormhole.bridge, signer);
programIds().wormhole.bridge,
request.signer,
);
setProgress({ setProgress({
message: `Waiting for ${walletName} transfer approval`, message: `Waiting for ${walletName} transfer approval`,
type: 'user', type: 'user',
@ -242,10 +234,10 @@ export const toSolana = async (
}); });
let res = await wh.lockAssets( let res = await wh.lockAssets(
request.asset, request.asset,
request.amountBN, amountBN,
request.recipient, request.recipient,
request.toChain, request.toChain,
request.nonce, nonce,
false, false,
); );
setProgress({ setProgress({

View File

@ -3,6 +3,7 @@ import {
getVerboseTokenName, getVerboseTokenName,
KnownTokenMap, KnownTokenMap,
} from '@oyster/common'; } from '@oyster/common';
import { TokenInfo } from '@solana/spl-token-registry';
export const getAssetName = ( export const getAssetName = (
parsedAssetAddress: string, parsedAssetAddress: string,
@ -48,6 +49,6 @@ export const chainToName = (chain?: ASSET_CHAIN) => {
return CHAIN_NAME[chain || ASSET_CHAIN.Ethereum]; return CHAIN_NAME[chain || ASSET_CHAIN.Ethereum];
}; };
export const filterModalSolTokens = (tokens: any[]) => { export const filterModalSolTokens = (tokens: TokenInfo[]) => {
return tokens; return tokens;
}; };