@ethersproject/abstract-provider#TransactionResponse TypeScript Examples
The following examples show how to use
@ethersproject/abstract-provider#TransactionResponse.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: PerpService.ts From sakeperp-arbitrageur with BSD 3-Clause "New" or "Revised" License | 6 votes |
async addMargin(
trader: Wallet,
exchangeAddr: string,
marginToBeAdded: Big,
overrides?: Overrides,
): Promise<TransactionResponse> {
const sakePerp = await this.createSakePerp(trader)
const tx = await sakePerp.functions.addMargin(
exchangeAddr,
{ d: PerpService.toWei(marginToBeAdded) },
{
gasLimit: 1_500_000,
...overrides,
},
)
this.log.jinfo({
event: "AddMarginTxSent",
params: {
trader: trader.address,
amm: exchangeAddr,
marginToBeRemoved: +marginToBeAdded.toFixed(),
txHash: tx.hash,
gasPrice: tx.gasPrice.toString(),
nonce: tx.nonce,
},
})
return tx
}
Example #2
Source File: TransactionManifest.ts From mStable-apps with GNU Lesser General Public License v3.0 | 6 votes |
async send(gasLimit?: BigNumber, gasPrice?: number): Promise<TransactionResponse> {
let response: TransactionResponse
try {
const args = await this.addGasSettings(gasLimit, gasPrice)
response = await this.contract.functions[this.fn](...args)
} catch (error) {
// MetaMask error messages are in a `data` property
const txMessage = error.data?.message || error.message
throw new Error(
!txMessage || txMessage.includes('always failing transaction') || txMessage.includes('transaction may fail')
? 'Transaction failed - if this problem persists, contact mStable team.'
: txMessage,
)
}
if (!response?.hash) {
throw new Error('Unable to send; missing transaction hash')
}
return response
}
Example #3
Source File: PerpService.ts From sakeperp-arbitrageur with BSD 3-Clause "New" or "Revised" License | 6 votes |
async removeMargin(
trader: Wallet,
exchangeAddr: string,
marginToBeRemoved: Big,
overrides?: Overrides,
): Promise<TransactionResponse> {
const sakePerp = await this.createSakePerp(trader)
const tx = await sakePerp.functions.removeMargin(
exchangeAddr,
{ d: PerpService.toWei(marginToBeRemoved) },
{
gasLimit: 1_500_000,
...overrides,
},
)
this.log.jinfo({
event: "RemoveMarginTxSent",
params: {
trader: trader.address,
amm: exchangeAddr,
marginToBeRemoved: +marginToBeRemoved.toFixed(),
txHash: tx.hash,
gasPrice: tx.gasPrice.toString(),
nonce: tx.nonce,
},
})
return tx
}
Example #4
Source File: PerpService.ts From sakeperp-arbitrageur with BSD 3-Clause "New" or "Revised" License | 6 votes |
async closePosition(
trader: Wallet,
exchangeAddr: string,
exchangePair: string,
minBaseAssetAmount: Big = Big(0),
overrides?: Overrides,
): Promise<TransactionResponse> {
const sakePerp = await this.createSakePerp(trader)
const tx = await sakePerp.functions.closePosition(
exchangeAddr,
{ d: PerpService.toWei(minBaseAssetAmount) },
{
gasLimit: 2_500_000,
...overrides,
},
)
this.log.jinfo({
event: "ClosePositionTxSent",
params: {
trader: trader.address,
exchangePair: exchangePair,
txHash: tx.hash,
gasPrice: tx.gasPrice.toString(),
nonce: tx.nonce,
},
})
return tx
}
Example #5
Source File: tune.ts From nova with GNU Affero General Public License v3.0 | 6 votes |
/**
* Finds the optimal missing gas estimate for an execution manager based on a single exec tx.
*/
async function findOptimalMissingGasEstimate(
L1_NovaExecutionManager: L1NovaExecutionManager,
tx: Promise<TransactionResponse>
) {
const { gasUsed, logs } = await (await tx).wait();
// Since we accept a generic TransactionResponse we have to parse the logs manually.
const execEvent = L1_NovaExecutionManager.interface.parseLog(logs[logs.length - 1]);
// We are assuming that the current gas config was the same when the
// tx was executed. Don't try to use tune on really old transactions!
const currentGasConfig = await L1_NovaExecutionManager.gasConfig();
const currentMissingGasEstimate = currentGasConfig.missingGasEstimate.toNumber();
const underestimateAmount = gasUsed.toNumber() - execEvent.args.gasUsed.toNumber();
return {
currentGasConfig,
currentMissingGasEstimate,
optimalMissingGasEstimate: currentMissingGasEstimate + underestimateAmount,
};
}
Example #6
Source File: snapshot.ts From trident with GNU General Public License v3.0 | 6 votes |
export async function snapshotGasCost(
x:
| TransactionResponse
| Promise<TransactionResponse>
| ContractTransaction
| Promise<ContractTransaction>
| TransactionReceipt
| Promise<BigNumber>
| BigNumber
| Contract
| Promise<Contract>
): Promise<void> {
const resolved = await x;
if ("deployTransaction" in resolved) {
const receipt = await resolved.deployTransaction.wait();
expect(receipt.gasUsed.toNumber()).toMatchSnapshot();
} else if ("wait" in resolved) {
const waited = await resolved.wait();
expect(waited.gasUsed.toNumber()).toMatchSnapshot();
} else if (BigNumber.isBigNumber(resolved)) {
expect(resolved.toNumber()).toMatchSnapshot();
}
}
Example #7
Source File: base-provider.ts From bodhi.js with Apache License 2.0 | 5 votes |
sendTransaction = async (signedTransaction: string | Promise<string>): Promise<TransactionResponse> => {
await this.getNetwork();
const hexTx = await Promise.resolve(signedTransaction).then((t) => hexlify(t));
const tx = parseTransaction(await signedTransaction);
if ((tx as any).confirmations === null || (tx as any).confirmations === undefined) {
(tx as any).confirmations = 0;
}
try {
const { extrinsic, transaction } = await this.prepareTransaction(hexTx);
//@TODO
// wait for tx in block
const result = await sendTx(this.api, extrinsic);
const blockHash = result.status.isInBlock ? result.status.asInBlock : result.status.asFinalized;
const header = await this._getBlockHeader(blockHash.toHex());
const blockNumber = header.number.toNumber();
const hash = extrinsic.hash.toHex();
return this._wrapTransaction(transaction, hash, blockNumber, blockHash.toHex());
} catch (err) {
const error = err as any;
for (let pattern of ERROR_PATTERN) {
const match = ((error.toString?.() || '') as string).match(pattern);
if (match) {
const errDetails = this.api.registry.findMetaError(new Uint8Array([parseInt(match[1]), parseInt(match[2])]));
// error.message is readonly, so construct a new error object
throw new Error(
JSON.stringify({
message: `${errDetails.section}.${errDetails.name}: ${errDetails.docs}`,
transaction: tx,
transactionHash: tx.hash
})
);
}
}
error.transaction = tx;
error.transactionHash = tx.hash;
throw error;
}
};
Example #8
Source File: tune.ts From nova with GNU Affero General Public License v3.0 | 5 votes |
/**
* Tunes an execution manager's missing gas estimate based on single exec tx.
*/
export async function tuneMissingGasEstimate(
L1_NovaExecutionManager: L1NovaExecutionManager,
tx: Promise<TransactionResponse>
) {
const { currentGasConfig, currentMissingGasEstimate, optimalMissingGasEstimate } =
await findOptimalMissingGasEstimate(L1_NovaExecutionManager, tx);
console.log();
const loader = ora({
text: chalk.gray(
`tuning missing gas estimate from ${chalk.magenta(
currentMissingGasEstimate.toString()
)} to ${chalk.magenta(optimalMissingGasEstimate.toString())}\n`
),
color: "magenta",
indent: 6,
}).start();
// Add a 500 gas buffer for a bit of leeway.
const newMissingGasEstimate = optimalMissingGasEstimate + 500;
// Update the missing gas estimate on-chain.
await (
await L1_NovaExecutionManager.updateGasConfig({
...currentGasConfig,
missingGasEstimate: newMissingGasEstimate,
})
).wait();
loader.stopAndPersist({
symbol: chalk.magenta("✓"),
text: chalk.gray(
`tuned missing gas estimate from ${chalk.magenta(
currentMissingGasEstimate.toString()
)} to ${chalk.magenta(optimalMissingGasEstimate.toString())}\n`
),
});
loader.indent = 0;
}
Example #9
Source File: EthService.ts From sakeperp-arbitrageur with BSD 3-Clause "New" or "Revised" License | 5 votes |
static async supervise(
signer: Wallet,
tx: TransactionResponse,
timeout: number,
retry = 3,
): Promise<TransactionReceipt> {
return new Promise((resolve, reject) => {
// Set timeout for sending cancellation tx at double the gas price
const timeoutId = setTimeout(async () => {
const cancelTx = await signer.sendTransaction({
to: signer.address,
value: 0,
gasPrice: tx.gasPrice.mul(2), // TODO Make configurable?
nonce: tx.nonce,
})
await EthService.log.warn(
JSON.stringify({
event: "txCancelling",
params: {
tx: tx.hash,
txGasPrice: tx.gasPrice.toString(),
cancelTx: cancelTx.hash,
cancelTxGasPrice: cancelTx.gasPrice.toString(),
nonce: cancelTx.nonce,
},
}),
)
// Yo dawg I heard you like cancelling tx so
// we put a cancel in your cancel tx so you can supervise while you supervise
if (retry > 0) {
await EthService.supervise(signer, cancelTx, timeout, retry - 1)
} else {
await cancelTx.wait()
}
reject({
reason: "timeout",
tx: tx.hash,
cancelTx: cancelTx.hash,
})
}, timeout)
// Otherwise, resolve normally if the original tx is confirmed
tx.wait().then(result => {
clearTimeout(timeoutId)
resolve(result)
})
})
}
Example #10
Source File: PerpService.ts From sakeperp-arbitrageur with BSD 3-Clause "New" or "Revised" License | 5 votes |
async openPosition(
trader: Wallet,
exchangePair: string,
exchangeAddr: string,
side: Side,
quoteAssetAmount: Big,
leverage: Big,
minBaseAssetAmount: Big = Big(0),
overrides?: Overrides,
): Promise<TransactionResponse> {
const sakePerp = await this.createSakePerp(trader)
// if the tx gonna fail it will throw here
// const gasEstimate = await sakePerp.estimateGas.openPosition(
// exchangeAddr,
// side.valueOf(),
// { d: PerpService.toWei(quoteAssetAmount) },
// { d: PerpService.toWei(leverage) },
// { d: PerpService.toWei(minBaseAssetAmount) },
// )
const tx = await sakePerp.functions.openPosition(
exchangeAddr,
side.valueOf(),
{ d: PerpService.toWei(quoteAssetAmount) },
{ d: PerpService.toWei(leverage) },
{ d: PerpService.toWei(minBaseAssetAmount) },
{
// add a margin for gas limit since its estimation was sometimes too tight
// gasLimit: BigNumber.from(
// Big(gasEstimate.toString())
// .mul(Big(1.2))
// .toFixed(0),
// ),
gasLimit: 2_500_000,
...overrides,
},
)
this.log.jinfo({
event: "OpenPositionTxSent",
params: {
exchangePair: exchangePair,
trader: trader.address,
amm: exchangeAddr,
side,
quoteAssetAmount: +quoteAssetAmount,
leverage: +leverage,
minBaseAssetAmount: +minBaseAssetAmount,
txHash: tx.hash,
gasPrice: tx.gasPrice.toString(),
nonce: tx.nonce,
},
})
return tx
}
Example #11
Source File: base-provider.ts From bodhi.js with Apache License 2.0 | 5 votes |
// Queries
getTransaction = (txHash: string): Promise<TransactionResponse> =>
throwNotImplemented('getTransaction (deprecated: please use getTransactionByHash)');
Example #12
Source File: transactionErrors.d.ts From tx2uml with MIT License | 5 votes |
getTransactionError: (tx: TransactionResponse, receipt: TransactionReceipt, provider: Provider) => Promise<string>
Example #13
Source File: transactionErrors.ts From tx2uml with MIT License | 5 votes |
getTransactionError = async (
tx: TransactionResponse,
receipt: TransactionReceipt,
provider: Provider
): Promise<string> => {
if (typeof tx !== "object") {
throw TypeError(`tx argument ${tx} must be a transaction object`)
}
if (typeof receipt !== "object") {
throw TypeError(
`receipt argument ${receipt} must be a transaction receipt object`
)
}
if (receipt.status) {
throw TypeError(
"Transaction did not fail. Can only read the revert reason from failed transactions"
)
}
if (!receipt.transactionHash) {
throw TypeError(`There is no transaction hash on the receipt object`)
}
if (receipt.gasUsed === tx.gasLimit) {
throw Error("Transaction failed as it ran out of gas.")
}
let rawMessageData
try {
const result = await provider.call(
{
...tx,
},
receipt.blockNumber
)
// Trim the 0x prefix
rawMessageData = result.slice(2)
} catch (e) {
if (e.message.startsWith("Node error: ")) {
// Trim "Node error: "
const errorObjectStr = e.message.slice(12)
// Parse the error object
const errorObject = JSON.parse(errorObjectStr)
if (!errorObject.data) {
throw Error(
"Failed to parse data field error object:" + errorObjectStr
)
}
if (errorObject.data.startsWith("Reverted 0x")) {
// Trim "Reverted 0x" from the data field
rawMessageData = errorObject.data.slice(11)
} else if (errorObject.data.startsWith("0x")) {
// Trim "0x" from the data field
rawMessageData = errorObject.data.slice(2)
} else {
throw Error(
"Failed to parse data field of error object:" +
errorObjectStr
)
}
} else {
throw Error(
"Failed to parse error message from Ethereum call: " + e.message
)
}
}
return parseReasonCode(rawMessageData)
}
Example #14
Source File: usePromiseTransaction.ts From useDApp with MIT License | 5 votes |
export function usePromiseTransaction(chainId: number | undefined, options?: TransactionOptions) {
const [state, setState] = useState<TransactionStatus>({ status: 'None' })
const { addTransaction } = useTransactionsContext()
const { addNotification } = useNotificationsContext()
const resetState = useCallback(() => {
setState({ status: 'None' })
}, [setState])
const promiseTransaction = useCallback(
async (transactionPromise: Promise<TransactionResponse>) => {
if (!chainId) return
let transaction: TransactionResponse | undefined = undefined
try {
setState({ status: 'PendingSignature', chainId })
transaction = await transactionPromise
setState({ transaction, status: 'Mining', chainId })
addTransaction({
transaction: {
...transaction,
chainId: chainId,
},
submittedAt: Date.now(),
transactionName: options?.transactionName,
})
const receipt = await transaction.wait()
setState({ receipt, transaction, status: 'Success', chainId })
return receipt
} catch (e: any) {
const errorMessage = e.error?.data?.message ?? e.error?.message ?? e.reason ?? e.data?.message ?? e.message
if (transaction) {
const droppedAndReplaced = isDroppedAndReplaced(e)
if (droppedAndReplaced) {
const status: TransactionState = e.receipt.status === 0 ? 'Fail' : 'Success'
const type = status === 'Fail' ? 'transactionFailed' : 'transactionSucceed'
addNotification({
notification: {
type,
submittedAt: Date.now(),
transaction: e.replacement,
receipt: e.receipt,
transactionName: e.replacement?.transactionName,
originalTransaction: transaction,
},
chainId,
})
setState({
status,
transaction: e.replacement,
originalTransaction: transaction,
receipt: e.receipt,
errorMessage,
chainId,
})
} else {
setState({ status: 'Fail', transaction, receipt: e.receipt, errorMessage, chainId })
}
} else {
setState({ status: 'Exception', errorMessage, chainId })
}
return undefined
}
},
[chainId, setState, addTransaction, options]
)
return { promiseTransaction, state, resetState }
}
Example #15
Source File: transactionsReducer.test.ts From useDApp with MIT License | 5 votes |
describe('transactionsReducer', () => {
it('addTransaction', () => {
const transaction: StoredTransaction = {
transaction: { chainId: 1 } as TransactionResponse,
submittedAt: 10,
}
expect(transactionReducer({}, { type: 'ADD_TRANSACTION', payload: transaction })).to.deep.eq({
1: [transaction],
})
})
it('correct order', () => {
const initial: StoredTransaction = {
transaction: { chainId: 1 } as TransactionResponse,
submittedAt: 10,
}
const added: StoredTransaction = {
transaction: { chainId: 1 } as TransactionResponse,
submittedAt: 30,
}
const newState = transactionReducer({ 1: [initial] }, { type: 'ADD_TRANSACTION', payload: added })
expect(newState).to.deep.eq({ 1: [added, initial] })
})
it('update transactions', () => {
const initialTransactions: StoredTransaction[] = [
{ transaction: { chainId: 1 } as TransactionResponse, submittedAt: 10 },
{ transaction: { chainId: 1 } as TransactionResponse, submittedAt: 15 },
{ transaction: { chainId: 1 } as TransactionResponse, submittedAt: 20 },
]
const newTransactions = initialTransactions.map((tx) => ({ ...tx, lastCheckedBlockNumber: 12 }))
const newState = transactionReducer(
{ 1: initialTransactions },
{ type: 'UPDATE_TRANSACTIONS', chainId: 1, transactions: newTransactions }
)
expect(newState).to.deep.eq({ 1: newTransactions })
})
})
Example #16
Source File: contractCallOutOfGasMock.ts From useDApp with MIT License | 5 votes |
transferOutOfGasMock = (): TransactionResponse => {
return {
wait: (): Promise<TransactionReceipt> => {
return Promise.reject({ reason: 'out of gas' })
},
} as TransactionResponse
}
Example #17
Source File: index.ts From ethereum-sdk with MIT License | 5 votes |
constructor(private readonly tx: TransactionResponse) {}
Example #18
Source File: Provider.ts From evm-provider.js with Apache License 2.0 | 5 votes |
/**
* Unimplemented, will always fail.
*/
async getTransaction(transactionHash: string): Promise<TransactionResponse> {
return this._fail('getTransaction');
}
Example #19
Source File: Provider.ts From evm-provider.js with Apache License 2.0 | 5 votes |
/**
* Unimplemented
*/
async sendTransaction(
signedTransaction: string | Promise<string>
): Promise<TransactionResponse> {
return this._fail('sendTransaction');
}
Example #20
Source File: MigrateV1Exchange.tsx From sushiswap-exchange with GNU General Public License v3.0 | 4 votes |
function V1PairMigration({ liquidityTokenAmount, token }: { liquidityTokenAmount: TokenAmount; token: Token }) {
const { account, chainId } = useActiveWeb3React()
const totalSupply = useTotalSupply(liquidityTokenAmount.token)
const exchangeETHBalance = useETHBalances([liquidityTokenAmount.token.address])?.[liquidityTokenAmount.token.address]
const exchangeTokenBalance = useTokenBalance(liquidityTokenAmount.token.address, token)
const [v2PairState, v2Pair] = usePair(chainId ? WETH[chainId] : undefined, token)
const isFirstLiquidityProvider: boolean = v2PairState === PairState.NOT_EXISTS
const v2SpotPrice = chainId && v2Pair ? v2Pair.reserveOf(token).divide(v2Pair.reserveOf(WETH[chainId])) : undefined
const [confirmingMigration, setConfirmingMigration] = useState<boolean>(false)
const [pendingMigrationHash, setPendingMigrationHash] = useState<string | null>(null)
const shareFraction: Fraction = totalSupply ? new Percent(liquidityTokenAmount.raw, totalSupply.raw) : ZERO_FRACTION
const ethWorth: CurrencyAmount = exchangeETHBalance
? CurrencyAmount.ether(exchangeETHBalance.multiply(shareFraction).multiply(WEI_DENOM).quotient)
: CurrencyAmount.ether(ZERO)
const tokenWorth: TokenAmount = exchangeTokenBalance
? new TokenAmount(token, shareFraction.multiply(exchangeTokenBalance.raw).quotient)
: new TokenAmount(token, ZERO)
const [approval, approve] = useApproveCallback(liquidityTokenAmount, MIGRATOR_ADDRESS)
const v1SpotPrice =
exchangeTokenBalance && exchangeETHBalance
? exchangeTokenBalance.divide(new Fraction(exchangeETHBalance.raw, WEI_DENOM))
: null
const priceDifferenceFraction: Fraction | undefined =
v1SpotPrice && v2SpotPrice
? v1SpotPrice
.divide(v2SpotPrice)
.multiply('100')
.subtract('100')
: undefined
const priceDifferenceAbs: Fraction | undefined = priceDifferenceFraction?.lessThan(ZERO)
? priceDifferenceFraction?.multiply('-1')
: priceDifferenceFraction
const minAmountETH: JSBI | undefined =
v2SpotPrice && tokenWorth
? tokenWorth
.divide(v2SpotPrice)
.multiply(WEI_DENOM)
.multiply(ALLOWED_OUTPUT_MIN_PERCENT).quotient
: ethWorth?.numerator
const minAmountToken: JSBI | undefined =
v2SpotPrice && ethWorth
? ethWorth
.multiply(v2SpotPrice)
.multiply(JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(token.decimals)))
.multiply(ALLOWED_OUTPUT_MIN_PERCENT).quotient
: tokenWorth?.numerator
const addTransaction = useTransactionAdder()
const isMigrationPending = useIsTransactionPending(pendingMigrationHash ?? undefined)
const migrator = useV2MigratorContract()
const migrate = useCallback(() => {
if (!minAmountToken || !minAmountETH || !migrator) return
setConfirmingMigration(true)
migrator
.migrate(
token.address,
minAmountToken.toString(),
minAmountETH.toString(),
account,
Math.floor(new Date().getTime() / 1000) + DEFAULT_DEADLINE_FROM_NOW
)
.then((response: TransactionResponse) => {
ReactGA.event({
category: 'Migrate',
action: 'V1->V2',
label: token?.symbol
})
addTransaction(response, {
summary: `Migrate ${token.symbol} liquidity to V2`
})
setPendingMigrationHash(response.hash)
})
.catch(() => {
setConfirmingMigration(false)
})
}, [minAmountToken, minAmountETH, migrator, token, account, addTransaction])
const noLiquidityTokens = !!liquidityTokenAmount && liquidityTokenAmount.equalTo(ZERO)
const largePriceDifference = !!priceDifferenceAbs && !priceDifferenceAbs.lessThan(JSBI.BigInt(5))
const isSuccessfullyMigrated = !!pendingMigrationHash && noLiquidityTokens
return (
<AutoColumn gap="20px">
<TYPE.body my={9} style={{ fontWeight: 400 }}>
This tool will safely migrate your V1 liquidity to V2 with minimal price risk. The process is completely
trustless thanks to the{' '}
{chainId && (
<ExternalLink href={getEtherscanLink(chainId, MIGRATOR_ADDRESS, 'address')}>
<TYPE.blue display="inline">Uniswap migration contract↗</TYPE.blue>
</ExternalLink>
)}
.
</TYPE.body>
{!isFirstLiquidityProvider && largePriceDifference ? (
<YellowCard>
<TYPE.body style={{ marginBottom: 8, fontWeight: 400 }}>
It{"'"}s best to deposit liquidity into SushiSwap LP Token at a price you believe is correct. If the V2 price seems
incorrect, you can either make a swap to move the price or wait for someone else to do so.
</TYPE.body>
<AutoColumn gap="8px">
<RowBetween>
<TYPE.body>V1 Price:</TYPE.body>
<TYPE.black>
{v1SpotPrice?.toSignificant(6)} {token.symbol}/ETH
</TYPE.black>
</RowBetween>
<RowBetween>
<div />
<TYPE.black>
{v1SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
</TYPE.black>
</RowBetween>
<RowBetween>
<TYPE.body>V2 Price:</TYPE.body>
<TYPE.black>
{v2SpotPrice?.toSignificant(6)} {token.symbol}/ETH
</TYPE.black>
</RowBetween>
<RowBetween>
<div />
<TYPE.black>
{v2SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
</TYPE.black>
</RowBetween>
<RowBetween>
<TYPE.body color="inherit">Price Difference:</TYPE.body>
<TYPE.black color="inherit">{priceDifferenceAbs?.toSignificant(4)}%</TYPE.black>
</RowBetween>
</AutoColumn>
</YellowCard>
) : null}
{isFirstLiquidityProvider && (
<PinkCard>
<TYPE.body style={{ marginBottom: 8, fontWeight: 400 }}>
You are the first liquidity provider for this pair on SushiSwap LP Token. Your liquidity will be migrated at the
current V1 price. Your transaction cost also includes the gas to create the pool.
</TYPE.body>
<AutoColumn gap="8px">
<RowBetween>
<TYPE.body>V1 Price:</TYPE.body>
<TYPE.black>
{v1SpotPrice?.toSignificant(6)} {token.symbol}/ETH
</TYPE.black>
</RowBetween>
<RowBetween>
<div />
<TYPE.black>
{v1SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
</TYPE.black>
</RowBetween>
</AutoColumn>
</PinkCard>
)}
<LightCard>
<V1LiquidityInfo
token={token}
liquidityTokenAmount={liquidityTokenAmount}
tokenWorth={tokenWorth}
ethWorth={ethWorth}
/>
<div style={{ display: 'flex', marginTop: '1rem' }}>
<AutoColumn gap="12px" style={{ flex: '1', marginRight: 12 }}>
<ButtonConfirmed
confirmed={approval === ApprovalState.APPROVED}
disabled={approval !== ApprovalState.NOT_APPROVED}
onClick={approve}
>
{approval === ApprovalState.PENDING ? (
<Dots>Approving</Dots>
) : approval === ApprovalState.APPROVED ? (
'Approved'
) : (
'Approve'
)}
</ButtonConfirmed>
</AutoColumn>
<AutoColumn gap="12px" style={{ flex: '1' }}>
<ButtonConfirmed
confirmed={isSuccessfullyMigrated}
disabled={
isSuccessfullyMigrated ||
noLiquidityTokens ||
isMigrationPending ||
approval !== ApprovalState.APPROVED ||
confirmingMigration
}
onClick={migrate}
>
{isSuccessfullyMigrated ? 'Success' : isMigrationPending ? <Dots>Migrating</Dots> : 'Migrate'}
</ButtonConfirmed>
</AutoColumn>
</div>
</LightCard>
<TYPE.darkGray style={{ textAlign: 'center' }}>
{`Your Uniswap V1 ${token.symbol}/ETH liquidity will become SushiSwap LP Token ${token.symbol}/ETH liquidity.`}
</TYPE.darkGray>
</AutoColumn>
)
}
Example #21
Source File: Signer.ts From evm-provider.js with Apache License 2.0 | 4 votes |
/**
*
* @param transaction
* @returns A promise that resolves to the transaction's response
*/
async sendTransaction(
_transaction: Deferrable<TransactionRequest>
): Promise<TransactionResponse> {
this._checkProvider('sendTransaction');
const signerAddress = await this.getSubstrateAddress();
const evmAddress = await this.getAddress();
// estimateResources requires the from parameter.
// However, when creating the contract, there is no from parameter in the tx
const transaction = {
from: evmAddress,
..._transaction
};
const resources = await this.provider.estimateResources(transaction);
// Multiply by 3.1
const gasLimit: BigNumber = resources.gas.mul(31).div(10);
let storageLimit: BigNumber;
// If the storage limit is supplied, override it from the estimateResources
if (transaction.customData) {
if ('storageLimit' in transaction.customData) {
storageLimit = transaction.customData.storageLimit;
if (isNumber(storageLimit)) {
storageLimit = BigNumber.from(storageLimit);
}
}
} else {
storageLimit = resources.storage.mul(31).div(10);
}
let totalLimit = await transaction.gasLimit;
if (totalLimit === null || totalLimit === undefined) {
totalLimit = gasLimit.add(storageLimit);
}
transaction.gasLimit = totalLimit;
const tx = await this.populateTransaction(transaction);
const data = tx.data;
const from = tx.from;
if (!data) {
return logger.throwError('Request data not found');
}
if (!from) {
return logger.throwError('Request from not found');
}
let extrinsic: SubmittableExtrinsic<'promise'>;
// @TODO create contract
if (!tx.to) {
extrinsic = this.provider.api.tx.evm.create(
tx.data,
toBN(tx.value),
toBN(gasLimit),
toBN(storageLimit.isNegative() ? 0 : storageLimit)
);
} else {
extrinsic = this.provider.api.tx.evm.call(
tx.to,
tx.data,
toBN(tx.value),
toBN(gasLimit),
toBN(storageLimit.isNegative() ? 0 : storageLimit)
);
}
await extrinsic.signAsync(signerAddress);
return new Promise((resolve, reject) => {
extrinsic
.send((result: SubmittableResult) => {
handleTxResponse(result, this.provider.api)
.then(() => {
resolve({
hash: extrinsic.hash.toHex(),
from: from || '',
confirmations: 0,
nonce: toBN(tx.nonce).toNumber(),
gasLimit: BigNumber.from(tx.gasLimit || '0'),
gasPrice: BigNumber.from(0),
data: dataToString(data),
value: BigNumber.from(tx.value || '0'),
chainId: 13939,
wait: (confirmations?: number): Promise<TransactionReceipt> => {
return this.provider._resolveTransactionReceipt(
extrinsic.hash.toHex(),
result.status.asInBlock.toHex(),
from
);
}
});
})
.catch(({ message, result }) => {
reject(message);
});
})
.catch((error) => {
reject(error && error.message);
});
});
}
Example #22
Source File: RemoveV1Exchange.tsx From luaswap-interface with GNU General Public License v3.0 | 4 votes |
function V1PairRemoval({
exchangeContract,
liquidityTokenAmount,
token
}: {
exchangeContract: Contract
liquidityTokenAmount: TokenAmount
token: Token
}) {
const { chainId } = useActiveWeb3React()
const totalSupply = useTotalSupply(liquidityTokenAmount.token)
const exchangeETHBalance = useETHBalances([liquidityTokenAmount.token.address])?.[liquidityTokenAmount.token.address]
const exchangeTokenBalance = useTokenBalance(liquidityTokenAmount.token.address, token)
const [confirmingRemoval, setConfirmingRemoval] = useState<boolean>(false)
const [pendingRemovalHash, setPendingRemovalHash] = useState<string | null>(null)
const shareFraction: Fraction = totalSupply ? new Percent(liquidityTokenAmount.raw, totalSupply.raw) : ZERO_FRACTION
const ethWorth: CurrencyAmount = exchangeETHBalance
? CurrencyAmount.ether(exchangeETHBalance.multiply(shareFraction).multiply(WEI_DENOM).quotient)
: CurrencyAmount.ether(ZERO)
const tokenWorth: TokenAmount = exchangeTokenBalance
? new TokenAmount(token, shareFraction.multiply(exchangeTokenBalance.raw).quotient)
: new TokenAmount(token, ZERO)
const addTransaction = useTransactionAdder()
const isRemovalPending = useIsTransactionPending(pendingRemovalHash ?? undefined)
const remove = useCallback(() => {
if (!liquidityTokenAmount) return
setConfirmingRemoval(true)
exchangeContract
.removeLiquidity(
liquidityTokenAmount.raw.toString(),
1, // min_eth, this is safe because we're removing liquidity
1, // min_tokens, this is safe because we're removing liquidity
Math.floor(new Date().getTime() / 1000) + DEFAULT_DEADLINE_FROM_NOW
)
.then((response: TransactionResponse) => {
ReactGA.event({
category: 'Remove',
action: 'V1',
label: token?.symbol
})
addTransaction(response, {
summary: `Remove ${chainId && token.equals(WETH[chainId]) ? 'WETH' : token.symbol}/ETH V1 liquidity`
})
setPendingRemovalHash(response.hash)
})
.catch((error: Error) => {
console.error(error)
setConfirmingRemoval(false)
})
}, [exchangeContract, liquidityTokenAmount, token, chainId, addTransaction])
const noLiquidityTokens = !!liquidityTokenAmount && liquidityTokenAmount.equalTo(ZERO)
const isSuccessfullyRemoved = !!pendingRemovalHash && noLiquidityTokens
return (
<AutoColumn gap="20px">
<TYPE.body my={9} style={{ fontWeight: 400 }}>
This tool will remove your V1 liquidity and send the underlying assets to your wallet.
</TYPE.body>
<LightCard>
<V1LiquidityInfo
token={token}
liquidityTokenAmount={liquidityTokenAmount}
tokenWorth={tokenWorth}
ethWorth={ethWorth}
/>
<div style={{ display: 'flex', marginTop: '1rem' }}>
<ButtonConfirmed
confirmed={isSuccessfullyRemoved}
disabled={isSuccessfullyRemoved || noLiquidityTokens || isRemovalPending || confirmingRemoval}
onClick={remove}
>
{isSuccessfullyRemoved ? 'Success' : isRemovalPending ? <Dots>Removing</Dots> : 'Remove'}
</ButtonConfirmed>
</div>
</LightCard>
<TYPE.darkGray style={{ textAlign: 'center' }}>
{`Your LuaSwap V1 ${
chainId && token.equals(WETH[chainId]) ? 'WETH' : token.symbol
}/ETH liquidity will be redeemed for underlying assets.`}
</TYPE.darkGray>
</AutoColumn>
)
}
Example #23
Source File: Signer.ts From bodhi.js with Apache License 2.0 | 4 votes |
/**
*
* @param transaction
* @returns A promise that resolves to the transaction's response
*/
async sendTransaction(_transaction: Deferrable<TransactionRequest>): Promise<TransactionResponse> {
this._checkProvider('sendTransaction');
const signerAddress = await this.getSubstrateAddress();
const evmAddress = await this.getAddress();
// estimateResources requires the from parameter.
// However, when creating the contract, there is no from parameter in the tx
const transaction = {
from: evmAddress,
..._transaction
};
const resources = await this.provider.estimateResources(transaction);
let gasLimit: BigNumber;
let storageLimit: BigNumber;
let totalLimit = await transaction.gasLimit;
if (totalLimit === null || totalLimit === undefined) {
gasLimit = resources.gas;
storageLimit = resources.storage;
totalLimit = resources.gas.add(resources.storage);
} else {
const estimateTotalLimit = resources.gas.add(resources.storage);
gasLimit = BigNumber.from(totalLimit).mul(resources.gas).div(estimateTotalLimit).add(1);
storageLimit = BigNumber.from(totalLimit).mul(resources.storage).div(estimateTotalLimit).add(1);
}
transaction.gasLimit = totalLimit;
const tx = await this.populateTransaction(transaction);
const data = tx.data;
const from = tx.from;
if (!data) {
return logger.throwError('Request data not found');
}
if (!from) {
return logger.throwError('Request from not found');
}
let extrinsic: SubmittableExtrinsic<'promise'>;
// @TODO create contract
if (!tx.to) {
extrinsic = this.provider.api.tx.evm.create(
tx.data,
toBN(tx.value),
toBN(gasLimit),
toBN(storageLimit.isNegative() ? 0 : storageLimit),
tx.accessList || []
);
} else {
extrinsic = this.provider.api.tx.evm.call(
tx.to,
tx.data,
toBN(tx.value),
toBN(gasLimit),
toBN(storageLimit.isNegative() ? 0 : storageLimit),
tx.accessList || []
);
}
await extrinsic.signAsync(signerAddress);
return new Promise((resolve, reject) => {
extrinsic
.send((result: SubmittableResult) => {
handleTxResponse(result, this.provider.api)
.then(() => {
resolve({
hash: extrinsic.hash.toHex(),
from: from || '',
confirmations: 0,
nonce: toBN(tx.nonce).toNumber(),
gasLimit: BigNumber.from(tx.gasLimit || '0'),
gasPrice: BigNumber.from(1),
data: dataToString(data),
value: BigNumber.from(tx.value || '0'),
chainId: +this.provider.api.consts.evmAccounts.chainId.toString(),
wait: (confirmations?: number): Promise<TransactionReceipt> => {
const hex = result.status.isInBlock
? result.status.asInBlock.toHex()
: result.status.asFinalized.toHex();
return this.provider.getTransactionReceiptAtBlock(extrinsic.hash.toHex(), hex);
}
});
})
.catch(reject);
})
.catch(reject);
});
}
Example #24
Source File: MigrateV1Exchange.tsx From luaswap-interface with GNU General Public License v3.0 | 4 votes |
function V1PairMigration({ liquidityTokenAmount, token }: { liquidityTokenAmount: TokenAmount; token: Token }) {
const { account, chainId } = useActiveWeb3React()
const totalSupply = useTotalSupply(liquidityTokenAmount.token)
const exchangeETHBalance = useETHBalances([liquidityTokenAmount.token.address])?.[liquidityTokenAmount.token.address]
const exchangeTokenBalance = useTokenBalance(liquidityTokenAmount.token.address, token)
const [v2PairState, v2Pair] = usePair(chainId ? WETH[chainId] : undefined, token)
const isFirstLiquidityProvider: boolean = v2PairState === PairState.NOT_EXISTS
const v2SpotPrice = chainId && v2Pair ? v2Pair.reserveOf(token).divide(v2Pair.reserveOf(WETH[chainId])) : undefined
const [confirmingMigration, setConfirmingMigration] = useState<boolean>(false)
const [pendingMigrationHash, setPendingMigrationHash] = useState<string | null>(null)
const shareFraction: Fraction = totalSupply ? new Percent(liquidityTokenAmount.raw, totalSupply.raw) : ZERO_FRACTION
const ethWorth: CurrencyAmount = exchangeETHBalance
? CurrencyAmount.ether(exchangeETHBalance.multiply(shareFraction).multiply(WEI_DENOM).quotient)
: CurrencyAmount.ether(ZERO)
const tokenWorth: TokenAmount = exchangeTokenBalance
? new TokenAmount(token, shareFraction.multiply(exchangeTokenBalance.raw).quotient)
: new TokenAmount(token, ZERO)
const [approval, approve] = useApproveCallback(liquidityTokenAmount, MIGRATOR_ADDRESS)
const v1SpotPrice =
exchangeTokenBalance && exchangeETHBalance
? exchangeTokenBalance.divide(new Fraction(exchangeETHBalance.raw, WEI_DENOM))
: null
const priceDifferenceFraction: Fraction | undefined =
v1SpotPrice && v2SpotPrice
? v1SpotPrice
.divide(v2SpotPrice)
.multiply('100')
.subtract('100')
: undefined
const priceDifferenceAbs: Fraction | undefined = priceDifferenceFraction?.lessThan(ZERO)
? priceDifferenceFraction?.multiply('-1')
: priceDifferenceFraction
const minAmountETH: JSBI | undefined =
v2SpotPrice && tokenWorth
? tokenWorth
.divide(v2SpotPrice)
.multiply(WEI_DENOM)
.multiply(ALLOWED_OUTPUT_MIN_PERCENT).quotient
: ethWorth?.numerator
const minAmountToken: JSBI | undefined =
v2SpotPrice && ethWorth
? ethWorth
.multiply(v2SpotPrice)
.multiply(JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(token.decimals)))
.multiply(ALLOWED_OUTPUT_MIN_PERCENT).quotient
: tokenWorth?.numerator
const addTransaction = useTransactionAdder()
const isMigrationPending = useIsTransactionPending(pendingMigrationHash ?? undefined)
const migrator = useV2MigratorContract()
const migrate = useCallback(() => {
if (!minAmountToken || !minAmountETH || !migrator) return
setConfirmingMigration(true)
migrator
.migrate(
token.address,
minAmountToken.toString(),
minAmountETH.toString(),
account,
Math.floor(new Date().getTime() / 1000) + DEFAULT_DEADLINE_FROM_NOW
)
.then((response: TransactionResponse) => {
ReactGA.event({
category: 'Migrate',
action: 'V1->V2',
label: token?.symbol
})
addTransaction(response, {
summary: `Migrate ${token.symbol} liquidity to V2`
})
setPendingMigrationHash(response.hash)
})
.catch(() => {
setConfirmingMigration(false)
})
}, [minAmountToken, minAmountETH, migrator, token, account, addTransaction])
const noLiquidityTokens = !!liquidityTokenAmount && liquidityTokenAmount.equalTo(ZERO)
const largePriceDifference = !!priceDifferenceAbs && !priceDifferenceAbs.lessThan(JSBI.BigInt(5))
const isSuccessfullyMigrated = !!pendingMigrationHash && noLiquidityTokens
return (
<AutoColumn gap="20px">
<TYPE.body my={9} style={{ fontWeight: 400 }}>
This tool will safely migrate your V1 liquidity to V2 with minimal price risk. The process is completely
trustless thanks to the{' '}
{chainId && (
<ExternalLink href={getEtherscanLink(chainId, MIGRATOR_ADDRESS, 'address')}>
<TYPE.blue display="inline">LuaSwap migration contract↗</TYPE.blue>
</ExternalLink>
)}
.
</TYPE.body>
{!isFirstLiquidityProvider && largePriceDifference ? (
<YellowCard>
<TYPE.body style={{ marginBottom: 8, fontWeight: 400 }}>
It{"'"}s best to deposit liquidity into LuaSwap V1 at a price you believe is correct. If the V2 price seems
incorrect, you can either make a swap to move the price or wait for someone else to do so.
</TYPE.body>
<AutoColumn gap="8px">
<RowBetween>
<TYPE.body>V1 Price:</TYPE.body>
<TYPE.black>
{v1SpotPrice?.toSignificant(6)} {token.symbol}/ETH
</TYPE.black>
</RowBetween>
<RowBetween>
<div />
<TYPE.black>
{v1SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
</TYPE.black>
</RowBetween>
<RowBetween>
<TYPE.body>V2 Price:</TYPE.body>
<TYPE.black>
{v2SpotPrice?.toSignificant(6)} {token.symbol}/ETH
</TYPE.black>
</RowBetween>
<RowBetween>
<div />
<TYPE.black>
{v2SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
</TYPE.black>
</RowBetween>
<RowBetween>
<TYPE.body color="inherit">Price Difference:</TYPE.body>
<TYPE.black color="inherit">{priceDifferenceAbs?.toSignificant(4)}%</TYPE.black>
</RowBetween>
</AutoColumn>
</YellowCard>
) : null}
{isFirstLiquidityProvider && (
<PinkCard>
<TYPE.body style={{ marginBottom: 8, fontWeight: 400 }}>
You are the first liquidity provider for this pair on LuaSwap V2. Your liquidity will be migrated at the
current V1 price. Your transaction cost also includes the gas to create the pool.
</TYPE.body>
<AutoColumn gap="8px">
<RowBetween>
<TYPE.body>V1 Price:</TYPE.body>
<TYPE.black>
{v1SpotPrice?.toSignificant(6)} {token.symbol}/ETH
</TYPE.black>
</RowBetween>
<RowBetween>
<div />
<TYPE.black>
{v1SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
</TYPE.black>
</RowBetween>
</AutoColumn>
</PinkCard>
)}
<LightCard>
<V1LiquidityInfo
token={token}
liquidityTokenAmount={liquidityTokenAmount}
tokenWorth={tokenWorth}
ethWorth={ethWorth}
/>
<div style={{ display: 'flex', marginTop: '1rem' }}>
<AutoColumn gap="12px" style={{ flex: '1', marginRight: 12 }}>
<ButtonConfirmed
confirmed={approval === ApprovalState.APPROVED}
disabled={approval !== ApprovalState.NOT_APPROVED}
onClick={approve}
>
{approval === ApprovalState.PENDING ? (
<Dots>Approving</Dots>
) : approval === ApprovalState.APPROVED ? (
'Approved'
) : (
'Approve'
)}
</ButtonConfirmed>
</AutoColumn>
<AutoColumn gap="12px" style={{ flex: '1' }}>
<ButtonConfirmed
confirmed={isSuccessfullyMigrated}
disabled={
isSuccessfullyMigrated ||
noLiquidityTokens ||
isMigrationPending ||
approval !== ApprovalState.APPROVED ||
confirmingMigration
}
onClick={migrate}
>
{isSuccessfullyMigrated ? 'Success' : isMigrationPending ? <Dots>Migrating</Dots> : 'Migrate'}
</ButtonConfirmed>
</AutoColumn>
</div>
</LightCard>
<TYPE.darkGray style={{ textAlign: 'center' }}>
{`Your LuaSwap V1 ${token.symbol}/ETH liquidity will become LuaSwap V2 ${token.symbol}/ETH liquidity.`}
</TYPE.darkGray>
</AutoColumn>
)
}
Example #25
Source File: RemoveV1Exchange.tsx From goose-frontend-amm with GNU General Public License v3.0 | 4 votes |
function V1PairRemoval({
exchangeContract,
liquidityTokenAmount,
token,
}: {
exchangeContract: Contract
liquidityTokenAmount: TokenAmount
token: Token
}) {
const { chainId } = useActiveWeb3React()
const totalSupply = useTotalSupply(liquidityTokenAmount.token)
const exchangeETHBalance = useETHBalances([liquidityTokenAmount.token.address])?.[liquidityTokenAmount.token.address]
const exchangeTokenBalance = useTokenBalance(liquidityTokenAmount.token.address, token)
const [confirmingRemoval, setConfirmingRemoval] = useState<boolean>(false)
const [pendingRemovalHash, setPendingRemovalHash] = useState<string | null>(null)
const shareFraction: Fraction = totalSupply ? new Percent(liquidityTokenAmount.raw, totalSupply.raw) : ZERO_FRACTION
const ethWorth: CurrencyAmount = exchangeETHBalance
? CurrencyAmount.ether(exchangeETHBalance.multiply(shareFraction).multiply(WEI_DENOM).quotient)
: CurrencyAmount.ether(ZERO)
const tokenWorth: TokenAmount = exchangeTokenBalance
? new TokenAmount(token, shareFraction.multiply(exchangeTokenBalance.raw).quotient)
: new TokenAmount(token, ZERO)
const addTransaction = useTransactionAdder()
const isRemovalPending = useIsTransactionPending(pendingRemovalHash ?? undefined)
const remove = useCallback(() => {
if (!liquidityTokenAmount) return
setConfirmingRemoval(true)
exchangeContract
.removeLiquidity(
liquidityTokenAmount.raw.toString(),
1, // min_eth, this is safe because we're removing liquidity
1, // min_tokens, this is safe because we're removing liquidity
Math.floor(new Date().getTime() / 1000) + DEFAULT_DEADLINE_FROM_NOW
)
.then((response: TransactionResponse) => {
addTransaction(response, {
summary: `Remove ${chainId && token.equals(WETH[chainId]) ? 'WETH' : token.symbol}/ETH V1 liquidity`,
})
setPendingRemovalHash(response.hash)
})
.catch((error: Error) => {
console.error(error)
setConfirmingRemoval(false)
})
}, [exchangeContract, liquidityTokenAmount, token, chainId, addTransaction])
const noLiquidityTokens = !!liquidityTokenAmount && liquidityTokenAmount.equalTo(ZERO)
const isSuccessfullyRemoved = !!pendingRemovalHash && noLiquidityTokens
return (
<AutoColumn gap="20px">
<Body my={9} style={{ fontWeight: 400 }}>
This tool will remove your V1 liquidity and send the underlying assets to your wallet.
</Body>
<LightCard>
<V1LiquidityInfo
token={token}
liquidityTokenAmount={liquidityTokenAmount}
tokenWorth={tokenWorth}
ethWorth={ethWorth}
/>
<div style={{ display: 'flex', marginTop: '1rem' }}>
<Button
variant={isSuccessfullyRemoved ? 'success' : 'primary'}
disabled={isSuccessfullyRemoved || noLiquidityTokens || isRemovalPending || confirmingRemoval}
onClick={remove}
>
{isSuccessfullyRemoved ? 'Success' : isRemovalPending ? <Dots>Removing</Dots> : 'Remove'}
</Button>
</div>
</LightCard>
<DarkGray style={{ textAlign: 'center' }}>
{`Your Uniswap V1 ${
chainId && token.equals(WETH[chainId]) ? 'WETH' : token.symbol
}/ETH liquidity will be redeemed for underlying assets.`}
</DarkGray>
</AutoColumn>
)
}
Example #26
Source File: MigrateV1Exchange.tsx From goose-frontend-amm with GNU General Public License v3.0 | 4 votes |
function V1PairMigration({ liquidityTokenAmount, token }: { liquidityTokenAmount: TokenAmount; token: Token }) {
const { account, chainId } = useActiveWeb3React()
const totalSupply = useTotalSupply(liquidityTokenAmount.token)
const exchangeETHBalance = useETHBalances([liquidityTokenAmount.token.address])?.[liquidityTokenAmount.token.address]
const exchangeTokenBalance = useTokenBalance(liquidityTokenAmount.token.address, token)
const [v2PairState, v2Pair] = usePair(chainId ? WETH[chainId] : undefined, token)
const isFirstLiquidityProvider: boolean = v2PairState === PairState.NOT_EXISTS
const v2SpotPrice = chainId && v2Pair ? v2Pair.reserveOf(token).divide(v2Pair.reserveOf(WETH[chainId])) : undefined
const [confirmingMigration, setConfirmingMigration] = useState<boolean>(false)
const [pendingMigrationHash, setPendingMigrationHash] = useState<string | null>(null)
const shareFraction: Fraction = totalSupply ? new Percent(liquidityTokenAmount.raw, totalSupply.raw) : ZERO_FRACTION
const ethWorth: CurrencyAmount = exchangeETHBalance
? CurrencyAmount.ether(exchangeETHBalance.multiply(shareFraction).multiply(WEI_DENOM).quotient)
: CurrencyAmount.ether(ZERO)
const tokenWorth: TokenAmount = exchangeTokenBalance
? new TokenAmount(token, shareFraction.multiply(exchangeTokenBalance.raw).quotient)
: new TokenAmount(token, ZERO)
const [approval, approve] = useApproveCallback(liquidityTokenAmount, MIGRATOR_ADDRESS)
const v1SpotPrice =
exchangeTokenBalance && exchangeETHBalance
? exchangeTokenBalance.divide(new Fraction(exchangeETHBalance.raw, WEI_DENOM))
: null
const priceDifferenceFraction: Fraction | undefined =
v1SpotPrice && v2SpotPrice ? v1SpotPrice.divide(v2SpotPrice).multiply('100').subtract('100') : undefined
const priceDifferenceAbs: Fraction | undefined = priceDifferenceFraction?.lessThan(ZERO)
? priceDifferenceFraction?.multiply('-1')
: priceDifferenceFraction
const minAmountETH: JSBI | undefined =
v2SpotPrice && tokenWorth
? tokenWorth.divide(v2SpotPrice).multiply(WEI_DENOM).multiply(ALLOWED_OUTPUT_MIN_PERCENT).quotient
: ethWorth?.numerator
const minAmountToken: JSBI | undefined =
v2SpotPrice && ethWorth
? ethWorth
.multiply(v2SpotPrice)
.multiply(JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(token.decimals)))
.multiply(ALLOWED_OUTPUT_MIN_PERCENT).quotient
: tokenWorth?.numerator
const addTransaction = useTransactionAdder()
const isMigrationPending = useIsTransactionPending(pendingMigrationHash ?? undefined)
const migrator = useV2MigratorContract()
const migrate = useCallback(() => {
if (!minAmountToken || !minAmountETH || !migrator) return
setConfirmingMigration(true)
migrator
.migrate(
token.address,
minAmountToken.toString(),
minAmountETH.toString(),
account,
Math.floor(new Date().getTime() / 1000) + DEFAULT_DEADLINE_FROM_NOW
)
.then((response: TransactionResponse) => {
addTransaction(response, {
summary: `Migrate ${token.symbol} liquidity to V2`,
})
setPendingMigrationHash(response.hash)
})
.catch(() => {
setConfirmingMigration(false)
})
}, [minAmountToken, minAmountETH, migrator, token, account, addTransaction])
const noLiquidityTokens = !!liquidityTokenAmount && liquidityTokenAmount.equalTo(ZERO)
const largePriceDifference = !!priceDifferenceAbs && !priceDifferenceAbs.lessThan(JSBI.BigInt(5))
const isSuccessfullyMigrated = !!pendingMigrationHash && noLiquidityTokens
return (
<AutoColumn gap="20px">
<Body my={9} style={{ fontWeight: 400 }}>
This tool will safely migrate your V1 liquidity to V2 with minimal price risk. The process is completely
trustless thanks to the{' '}
{chainId && (
<ExternalLink href={getEtherscanLink(chainId, MIGRATOR_ADDRESS, 'address')}>
<Blue display="inline">Uniswap migration contract↗</Blue>
</ExternalLink>
)}
.
</Body>
{!isFirstLiquidityProvider && largePriceDifference ? (
<YellowCard>
<Body style={{ marginBottom: 8, fontWeight: 400 }}>
It's best to deposit liquidity into Uniswap V2 at a price you believe is correct. If the V2 price seems
incorrect, you can either make a swap to move the price or wait for someone else to do so.
</Body>
<AutoColumn gap="8px">
<RowBetween>
<Body>V1 Price:</Body>
<Black>
{v1SpotPrice?.toSignificant(6)} {token.symbol}/ETH
</Black>
</RowBetween>
<RowBetween>
<div />
<Black>
{v1SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
</Black>
</RowBetween>
<RowBetween>
<Body>V2 Price:</Body>
<Black>
{v2SpotPrice?.toSignificant(6)} {token.symbol}/ETH
</Black>
</RowBetween>
<RowBetween>
<div />
<Black>
{v2SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
</Black>
</RowBetween>
<RowBetween>
<Body color="inherit">Price Difference:</Body>
<Black color="inherit">{priceDifferenceAbs?.toSignificant(4)}%</Black>
</RowBetween>
</AutoColumn>
</YellowCard>
) : null}
{isFirstLiquidityProvider && (
<PinkCard>
<Body style={{ marginBottom: 8, fontWeight: 400 }}>
You are the first liquidity provider for this pair on Uniswap V2. Your liquidity will be migrated at the
current V1 price. Your transaction cost also includes the gas to create the pool.
</Body>
<AutoColumn gap="8px">
<RowBetween>
<Body>V1 Price:</Body>
<Black>
{v1SpotPrice?.toSignificant(6)} {token.symbol}/ETH
</Black>
</RowBetween>
<RowBetween>
<div />
<Black>
{v1SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
</Black>
</RowBetween>
</AutoColumn>
</PinkCard>
)}
<LightCard>
<V1LiquidityInfo
token={token}
liquidityTokenAmount={liquidityTokenAmount}
tokenWorth={tokenWorth}
ethWorth={ethWorth}
/>
<div style={{ display: 'flex', marginTop: '1rem' }}>
<AutoColumn gap="12px" style={{ flex: '1', marginRight: 12 }}>
<Button
variant={approval === ApprovalState.APPROVED ? 'success' : 'primary'}
disabled={approval !== ApprovalState.NOT_APPROVED}
onClick={approve}
>
{approval === ApprovalState.PENDING ? (
<Dots>Approving</Dots>
) : approval === ApprovalState.APPROVED ? (
'Approved'
) : (
'Approve'
)}
</Button>
</AutoColumn>
<AutoColumn gap="12px" style={{ flex: '1' }}>
<Button
variant={isSuccessfullyMigrated ? 'success' : 'primary'}
disabled={
isSuccessfullyMigrated ||
noLiquidityTokens ||
isMigrationPending ||
approval !== ApprovalState.APPROVED ||
confirmingMigration
}
onClick={migrate}
>
{isSuccessfullyMigrated ? 'Success' : isMigrationPending ? <Dots>Migrating</Dots> : 'Migrate'}
</Button>
</AutoColumn>
</div>
</LightCard>
<DarkDray style={{ textAlign: 'center' }}>
{`Your Uniswap V1 ${token.symbol}/ETH liquidity will become Uniswap V2 ${token.symbol}/ETH liquidity.`}
</DarkDray>
</AutoColumn>
)
}
Example #27
Source File: RemoveV1Exchange.tsx From dyp with Do What The F*ck You Want To Public License | 4 votes |
function V1PairRemoval({
exchangeContract,
liquidityTokenAmount,
token
}: {
exchangeContract: Contract
liquidityTokenAmount: TokenAmount
token: Token
}) {
const { chainId } = useActiveWeb3React()
const totalSupply = useTotalSupply(liquidityTokenAmount.token)
const exchangeETHBalance = useETHBalances([liquidityTokenAmount.token.address])?.[liquidityTokenAmount.token.address]
const exchangeTokenBalance = useTokenBalance(liquidityTokenAmount.token.address, token)
const [confirmingRemoval, setConfirmingRemoval] = useState<boolean>(false)
const [pendingRemovalHash, setPendingRemovalHash] = useState<string | null>(null)
const shareFraction: Fraction = totalSupply ? new Percent(liquidityTokenAmount.raw, totalSupply.raw) : ZERO_FRACTION
const ethWorth: CurrencyAmount = exchangeETHBalance
? CurrencyAmount.ether(exchangeETHBalance.multiply(shareFraction).multiply(WEI_DENOM).quotient)
: CurrencyAmount.ether(ZERO)
const tokenWorth: TokenAmount = exchangeTokenBalance
? new TokenAmount(token, shareFraction.multiply(exchangeTokenBalance.raw).quotient)
: new TokenAmount(token, ZERO)
const addTransaction = useTransactionAdder()
const isRemovalPending = useIsTransactionPending(pendingRemovalHash ?? undefined)
const remove = useCallback(() => {
if (!liquidityTokenAmount) return
setConfirmingRemoval(true)
exchangeContract
.removeLiquidity(
liquidityTokenAmount.raw.toString(),
1, // min_eth, this is safe because we're removing liquidity
1, // min_tokens, this is safe because we're removing liquidity
Math.floor(new Date().getTime() / 1000) + DEFAULT_DEADLINE_FROM_NOW
)
.then((response: TransactionResponse) => {
ReactGA.event({
category: 'Remove',
action: 'V1',
label: token?.symbol
})
addTransaction(response, {
summary: `Remove ${chainId && token.equals(WETH[chainId]) ? 'WETH' : token.symbol}/ETH V1 liquidity`
})
setPendingRemovalHash(response.hash)
})
.catch((error: Error) => {
console.error(error)
setConfirmingRemoval(false)
})
}, [exchangeContract, liquidityTokenAmount, token, chainId, addTransaction])
const noLiquidityTokens = !!liquidityTokenAmount && liquidityTokenAmount.equalTo(ZERO)
const isSuccessfullyRemoved = !!pendingRemovalHash && noLiquidityTokens
return (
<AutoColumn gap="20px">
<TYPE.body my={9} style={{ fontWeight: 400 }}>
This tool will remove your V1 liquidity and send the underlying assets to your wallet.
</TYPE.body>
<LightCard>
<V1LiquidityInfo
token={token}
liquidityTokenAmount={liquidityTokenAmount}
tokenWorth={tokenWorth}
ethWorth={ethWorth}
/>
<div style={{ display: 'flex', marginTop: '1rem' }}>
<ButtonConfirmed
confirmed={isSuccessfullyRemoved}
disabled={isSuccessfullyRemoved || noLiquidityTokens || isRemovalPending || confirmingRemoval}
onClick={remove}
>
{isSuccessfullyRemoved ? 'Success' : isRemovalPending ? <Dots>Removing</Dots> : 'Remove'}
</ButtonConfirmed>
</div>
</LightCard>
<TYPE.darkGray style={{ textAlign: 'center' }}>
{`Your Uniswap V1 ${
chainId && token.equals(WETH[chainId]) ? 'WETH' : token.symbol
}/ETH liquidity will be redeemed for underlying assets.`}
</TYPE.darkGray>
</AutoColumn>
)
}
Example #28
Source File: MigrateV1Exchange.tsx From dyp with Do What The F*ck You Want To Public License | 4 votes |
function V1PairMigration({ liquidityTokenAmount, token }: { liquidityTokenAmount: TokenAmount; token: Token }) {
const { account, chainId } = useActiveWeb3React()
const totalSupply = useTotalSupply(liquidityTokenAmount.token)
const exchangeETHBalance = useETHBalances([liquidityTokenAmount.token.address])?.[liquidityTokenAmount.token.address]
const exchangeTokenBalance = useTokenBalance(liquidityTokenAmount.token.address, token)
const [v2PairState, v2Pair] = usePair(chainId ? WETH[chainId] : undefined, token)
const isFirstLiquidityProvider: boolean = v2PairState === PairState.NOT_EXISTS
const v2SpotPrice = chainId && v2Pair ? v2Pair.reserveOf(token).divide(v2Pair.reserveOf(WETH[chainId])) : undefined
const [confirmingMigration, setConfirmingMigration] = useState<boolean>(false)
const [pendingMigrationHash, setPendingMigrationHash] = useState<string | null>(null)
const shareFraction: Fraction = totalSupply ? new Percent(liquidityTokenAmount.raw, totalSupply.raw) : ZERO_FRACTION
const ethWorth: CurrencyAmount = exchangeETHBalance
? CurrencyAmount.ether(exchangeETHBalance.multiply(shareFraction).multiply(WEI_DENOM).quotient)
: CurrencyAmount.ether(ZERO)
const tokenWorth: TokenAmount = exchangeTokenBalance
? new TokenAmount(token, shareFraction.multiply(exchangeTokenBalance.raw).quotient)
: new TokenAmount(token, ZERO)
const [approval, approve] = useApproveCallback(liquidityTokenAmount, MIGRATOR_ADDRESS)
const v1SpotPrice =
exchangeTokenBalance && exchangeETHBalance
? exchangeTokenBalance.divide(new Fraction(exchangeETHBalance.raw, WEI_DENOM))
: null
const priceDifferenceFraction: Fraction | undefined =
v1SpotPrice && v2SpotPrice
? v1SpotPrice
.divide(v2SpotPrice)
.multiply('100')
.subtract('100')
: undefined
const priceDifferenceAbs: Fraction | undefined = priceDifferenceFraction?.lessThan(ZERO)
? priceDifferenceFraction?.multiply('-1')
: priceDifferenceFraction
const minAmountETH: JSBI | undefined =
v2SpotPrice && tokenWorth
? tokenWorth
.divide(v2SpotPrice)
.multiply(WEI_DENOM)
.multiply(ALLOWED_OUTPUT_MIN_PERCENT).quotient
: ethWorth?.numerator
const minAmountToken: JSBI | undefined =
v2SpotPrice && ethWorth
? ethWorth
.multiply(v2SpotPrice)
.multiply(JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(token.decimals)))
.multiply(ALLOWED_OUTPUT_MIN_PERCENT).quotient
: tokenWorth?.numerator
const addTransaction = useTransactionAdder()
const isMigrationPending = useIsTransactionPending(pendingMigrationHash ?? undefined)
const migrator = useV2MigratorContract()
const migrate = useCallback(() => {
if (!minAmountToken || !minAmountETH || !migrator) return
setConfirmingMigration(true)
migrator
.migrate(
token.address,
minAmountToken.toString(),
minAmountETH.toString(),
account,
Math.floor(new Date().getTime() / 1000) + DEFAULT_DEADLINE_FROM_NOW
)
.then((response: TransactionResponse) => {
ReactGA.event({
category: 'Migrate',
action: 'V1->V2',
label: token?.symbol
})
addTransaction(response, {
summary: `Migrate ${token.symbol} liquidity to V2`
})
setPendingMigrationHash(response.hash)
})
.catch(() => {
setConfirmingMigration(false)
})
}, [minAmountToken, minAmountETH, migrator, token, account, addTransaction])
const noLiquidityTokens = !!liquidityTokenAmount && liquidityTokenAmount.equalTo(ZERO)
const largePriceDifference = !!priceDifferenceAbs && !priceDifferenceAbs.lessThan(JSBI.BigInt(5))
const isSuccessfullyMigrated = !!pendingMigrationHash && noLiquidityTokens
return (
<AutoColumn gap="20px">
<TYPE.body my={9} style={{ fontWeight: 400 }}>
This tool will safely migrate your V1 liquidity to V2 with minimal price risk. The process is completely
trustless thanks to the{' '}
{chainId && (
<ExternalLink href={getEtherscanLink(chainId, MIGRATOR_ADDRESS, 'address')}>
<TYPE.blue display="inline">Uniswap migration contract↗</TYPE.blue>
</ExternalLink>
)}
.
</TYPE.body>
{!isFirstLiquidityProvider && largePriceDifference ? (
<YellowCard>
<TYPE.body style={{ marginBottom: 8, fontWeight: 400 }}>
It{"'"}s best to deposit liquidity into Uniswap V2 at a price you believe is correct. If the V2 price seems
incorrect, you can either make a swap to move the price or wait for someone else to do so.
</TYPE.body>
<AutoColumn gap="8px">
<RowBetween>
<TYPE.body>V1 Price:</TYPE.body>
<TYPE.black>
{v1SpotPrice?.toSignificant(6)} {token.symbol}/ETH
</TYPE.black>
</RowBetween>
<RowBetween>
<div />
<TYPE.black>
{v1SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
</TYPE.black>
</RowBetween>
<RowBetween>
<TYPE.body>V2 Price:</TYPE.body>
<TYPE.black>
{v2SpotPrice?.toSignificant(6)} {token.symbol}/ETH
</TYPE.black>
</RowBetween>
<RowBetween>
<div />
<TYPE.black>
{v2SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
</TYPE.black>
</RowBetween>
<RowBetween>
<TYPE.body color="inherit">Price Difference:</TYPE.body>
<TYPE.black color="inherit">{priceDifferenceAbs?.toSignificant(4)}%</TYPE.black>
</RowBetween>
</AutoColumn>
</YellowCard>
) : null}
{isFirstLiquidityProvider && (
<PinkCard>
<TYPE.body style={{ marginBottom: 8, fontWeight: 400 }}>
You are the first liquidity provider for this pair on Uniswap V2. Your liquidity will be migrated at the
current V1 price. Your transaction cost also includes the gas to create the pool.
</TYPE.body>
<AutoColumn gap="8px">
<RowBetween>
<TYPE.body>V1 Price:</TYPE.body>
<TYPE.black>
{v1SpotPrice?.toSignificant(6)} {token.symbol}/ETH
</TYPE.black>
</RowBetween>
<RowBetween>
<div />
<TYPE.black>
{v1SpotPrice?.invert()?.toSignificant(6)} ETH/{token.symbol}
</TYPE.black>
</RowBetween>
</AutoColumn>
</PinkCard>
)}
<LightCard>
<V1LiquidityInfo
token={token}
liquidityTokenAmount={liquidityTokenAmount}
tokenWorth={tokenWorth}
ethWorth={ethWorth}
/>
<div style={{ display: 'flex', marginTop: '1rem' }}>
<AutoColumn gap="12px" style={{ flex: '1', marginRight: 12 }}>
<ButtonConfirmed
confirmed={approval === ApprovalState.APPROVED}
disabled={approval !== ApprovalState.NOT_APPROVED}
onClick={approve}
>
{approval === ApprovalState.PENDING ? (
<Dots>Approving</Dots>
) : approval === ApprovalState.APPROVED ? (
'Approved'
) : (
'Approve'
)}
</ButtonConfirmed>
</AutoColumn>
<AutoColumn gap="12px" style={{ flex: '1' }}>
<ButtonConfirmed
confirmed={isSuccessfullyMigrated}
disabled={
isSuccessfullyMigrated ||
noLiquidityTokens ||
isMigrationPending ||
approval !== ApprovalState.APPROVED ||
confirmingMigration
}
onClick={migrate}
>
{isSuccessfullyMigrated ? 'Success' : isMigrationPending ? <Dots>Migrating</Dots> : 'Migrate'}
</ButtonConfirmed>
</AutoColumn>
</div>
</LightCard>
<TYPE.darkGray style={{ textAlign: 'center' }}>
{`Your Uniswap V1 ${token.symbol}/ETH liquidity will become Uniswap V2 ${token.symbol}/ETH liquidity.`}
</TYPE.darkGray>
</AutoColumn>
)
}
Example #29
Source File: RemoveV1Exchange.tsx From cheeseswap-interface with GNU General Public License v3.0 | 4 votes |
function V1PairRemoval({
exchangeContract,
liquidityTokenAmount,
token
}: {
exchangeContract: Contract
liquidityTokenAmount: TokenAmount
token: Token
}) {
const { chainId } = useActiveWeb3React()
const totalSupply = useTotalSupply(liquidityTokenAmount.token)
const exchangeETHBalance = useETHBalances([liquidityTokenAmount.token.address])?.[liquidityTokenAmount.token.address]
const exchangeTokenBalance = useTokenBalance(liquidityTokenAmount.token.address, token)
const [confirmingRemoval, setConfirmingRemoval] = useState<boolean>(false)
const [pendingRemovalHash, setPendingRemovalHash] = useState<string | null>(null)
const shareFraction: Fraction = totalSupply ? new Percent(liquidityTokenAmount.raw, totalSupply.raw) : ZERO_FRACTION
const ethWorth: CurrencyAmount = exchangeETHBalance
? CurrencyAmount.ether(exchangeETHBalance.multiply(shareFraction).multiply(WEI_DENOM).quotient)
: CurrencyAmount.ether(ZERO)
const tokenWorth: TokenAmount = exchangeTokenBalance
? new TokenAmount(token, shareFraction.multiply(exchangeTokenBalance.raw).quotient)
: new TokenAmount(token, ZERO)
const addTransaction = useTransactionAdder()
const isRemovalPending = useIsTransactionPending(pendingRemovalHash ?? undefined)
const remove = useCallback(() => {
if (!liquidityTokenAmount) return
setConfirmingRemoval(true)
exchangeContract
.removeLiquidity(
liquidityTokenAmount.raw.toString(),
1, // min_eth, this is safe because we're removing liquidity
1, // min_tokens, this is safe because we're removing liquidity
Math.floor(new Date().getTime() / 1000) + DEFAULT_DEADLINE_FROM_NOW
)
.then((response: TransactionResponse) => {
ReactGA.event({
category: 'Remove',
action: 'V1',
label: token?.symbol
})
addTransaction(response, {
summary: `Remove ${chainId && token.equals(WETH[chainId]) ? 'WETH' : token.symbol}/ETH V1 liquidity`
})
setPendingRemovalHash(response.hash)
})
.catch((error: Error) => {
console.error(error)
setConfirmingRemoval(false)
})
}, [exchangeContract, liquidityTokenAmount, token, chainId, addTransaction])
const noLiquidityTokens = !!liquidityTokenAmount && liquidityTokenAmount.equalTo(ZERO)
const isSuccessfullyRemoved = !!pendingRemovalHash && noLiquidityTokens
return (
<AutoColumn gap="20px">
<TYPE.body my={9} style={{ fontWeight: 600 }}>
This tool will remove your V1 liquidity and send the underlying assets to your wallet.
</TYPE.body>
<LightCard>
<V1LiquidityInfo
token={token}
liquidityTokenAmount={liquidityTokenAmount}
tokenWorth={tokenWorth}
ethWorth={ethWorth}
/>
<div style={{ display: 'flex', marginTop: '1rem' }}>
<ButtonConfirmed
confirmed={isSuccessfullyRemoved}
disabled={isSuccessfullyRemoved || noLiquidityTokens || isRemovalPending || confirmingRemoval}
onClick={remove}
>
{isSuccessfullyRemoved ? 'Success' : isRemovalPending ? <Dots>Removing</Dots> : 'Remove'}
</ButtonConfirmed>
</div>
</LightCard>
<TYPE.darkGray style={{ textAlign: 'center' }}>
{`Your Uniswap V1 ${
chainId && token.equals(WETH[chainId]) ? 'WETH' : token.symbol
}/ETH liquidity will be redeemed for underlying assets.`}
</TYPE.darkGray>
</AutoColumn>
)
}