ci(release): publish latest release

parent febe0e4b
IPFS hash of the deployment:
- CIDv0: `QmWXkZCZCVea5C5dkKAgH2jR3a8LWCFmJGedqiEaK21wHj`
- CIDv1: `bafybeidzwv7ldnoexuakxu7nxwvkvh7bcku5kxdixe7jdgal36mcur7doi`
- CIDv0: `QmZ2woTrzL5shcw9Ek6jqsLnHAMh1KGWGPkbeoMw3toRfC`
- CIDv1: `bafybeie645wzgpsz5isxptb3bdyo67rhtc4dfxjekenod6jvf6jxi7yqe4`
The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org).
......@@ -10,15 +10,10 @@ You can also access the Uniswap Interface from an IPFS gateway.
Your Uniswap settings are never remembered across different URLs.
IPFS gateways:
- https://bafybeidzwv7ldnoexuakxu7nxwvkvh7bcku5kxdixe7jdgal36mcur7doi.ipfs.dweb.link/
- https://bafybeidzwv7ldnoexuakxu7nxwvkvh7bcku5kxdixe7jdgal36mcur7doi.ipfs.cf-ipfs.com/
- [ipfs://QmWXkZCZCVea5C5dkKAgH2jR3a8LWCFmJGedqiEaK21wHj/](ipfs://QmWXkZCZCVea5C5dkKAgH2jR3a8LWCFmJGedqiEaK21wHj/)
- https://bafybeie645wzgpsz5isxptb3bdyo67rhtc4dfxjekenod6jvf6jxi7yqe4.ipfs.dweb.link/
- https://bafybeie645wzgpsz5isxptb3bdyo67rhtc4dfxjekenod6jvf6jxi7yqe4.ipfs.cf-ipfs.com/
- [ipfs://QmZ2woTrzL5shcw9Ek6jqsLnHAMh1KGWGPkbeoMw3toRfC/](ipfs://QmZ2woTrzL5shcw9Ek6jqsLnHAMh1KGWGPkbeoMw3toRfC/)
### 5.51.1 (2024-10-10)
### Bug Fixes
* **web:** Cab/web 5130 remove extension launch modal prod (#12891) 07a5a21
### 5.51.2 (2024-10-10)
web/5.51.1
\ No newline at end of file
web/5.51.2
\ No newline at end of file
......@@ -13,4 +13,3 @@ REACT_APP_SENTRY_ENABLED=true
REACT_APP_SENTRY_TRACES_SAMPLE_RATE=0.003
REACT_APP_STATSIG_PROXY_URL="https://interface.gateway.uniswap.org/v1/statsig-proxy"
REACT_APP_IS_UNISWAP_INTERFACE=true
REACT_APP_TRADING_API_KEY=gcZrVL9FxqnqjVytJd2z3oqImkOKRjZ49sF7WXy9
......@@ -11,6 +11,7 @@ import { PopupType, addPopup } from 'state/application/reducer'
import { handleUniswapXSignatureStep } from 'state/sagas/transactions/uniswapx'
import {
HandleOnChainStepParams,
addTransactionBreadcrumb,
getSwapTransactionInfo,
handleApprovalTransactionStep,
handleOnChainStep,
......@@ -271,8 +272,11 @@ function* uniswapXSwap(
}
function getDisplayableError(error: Error, step: TransactionStep): TransactionError | undefined {
const userRejected = didUserReject(error)
// If the user rejects a request, or it's a known interruption e.g. trade update, we handle gracefully / do not show error UI
if (didUserReject(error) || error instanceof HandledTransactionInterrupt) {
if (userRejected || error instanceof HandledTransactionInterrupt) {
const loggableMessage = userRejected ? 'user rejected request' : error.message // for user rejections, avoid logging redundant/long message
addTransactionBreadcrumb({ step, status: 'interrupted', data: { message: loggableMessage } })
return undefined
} else if (error instanceof TransactionError) {
return error // If the error was already formatted as a TransactionError, we just propagate
......
import { formatSwapSignedAnalyticsEventProperties } from 'lib/utils/analytics'
import { PopupType, addPopup } from 'state/application/reducer'
import { HandleSignatureStepParams, getSwapTransactionInfo, handleSignatureStep } from 'state/sagas/transactions/utils'
import {
HandleSignatureStepParams,
addTransactionBreadcrumb,
getSwapTransactionInfo,
handleSignatureStep,
} from 'state/sagas/transactions/utils'
import { addSignature } from 'state/signatures/reducer'
import { SignatureType, UnfilledUniswapXOrderDetails } from 'state/signatures/types'
import { call, put } from 'typed-redux-saga'
......@@ -49,6 +54,8 @@ export function* handleUniswapXSignatureStep(params: HandleUniswapXSignatureStep
throw new HandledTransactionInterrupt('User signed after deadline')
}
addTransactionBreadcrumb({ step, data: { routing, ...signatureDetails.swapInfo }, status: 'in progress' })
try {
yield* call(submitOrder, { signature, quote, routing })
} catch (error) {
......
......@@ -36,6 +36,7 @@ import { isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing
import { interruptTransactionFlow } from 'uniswap/src/utils/saga'
import { isSameAddress } from 'utilities/src/addresses'
import { percentFromFloat } from 'utilities/src/format/percent'
import { Sentry } from 'utilities/src/logger/Sentry'
import noop from 'utilities/src/react/noop'
import { currencyId } from 'utils/currencyId'
import { signTypedData } from 'utils/signing'
......@@ -51,6 +52,15 @@ export function* handleSignatureStep({ setCurrentStep, step, ignoreInterrupt, ac
// Add a watcher to check if the transaction flow is interrupted during this step
const { throwIfInterrupted } = yield* watchForInterruption(ignoreInterrupt)
addTransactionBreadcrumb({
step,
data: {
domain: JSON.stringify(step.domain),
values: JSON.stringify(step.values),
types: JSON.stringify(step.types),
},
})
// Trigger UI prompting user to accept
setCurrentStep({ step, accepted: false })
......@@ -59,6 +69,8 @@ export function* handleSignatureStep({ setCurrentStep, step, ignoreInterrupt, ac
// If the transaction flow was interrupted, throw an error after the step has completed
yield* call(throwIfInterrupted)
addTransactionBreadcrumb({ step, data: { signature }, status: 'complete' })
return signature
}
......@@ -81,12 +93,16 @@ export function* handleOnChainStep<T extends OnChainTransactionStep>(params: Han
const { chainId } = step.txRequest
const signer = yield* call(getSigner, account.address)
addTransactionBreadcrumb({ step, data: { ...info } })
// Avoid sending prompting a transaction if the user already submitted an equivalent tx, e.g. by closing and reopening a transaction flow
const duplicativeTx = yield* findDuplicativeTx(info, account, chainId, allowDuplicativeTx)
if (duplicativeTx) {
if (duplicativeTx.status === TransactionStatus.Confirmed) {
addTransactionBreadcrumb({ step, data: { duplicativeTx: true, hash: duplicativeTx.hash }, status: 'complete' })
return duplicativeTx.hash
} else {
addTransactionBreadcrumb({ step, data: { duplicativeTx: true, hash: duplicativeTx.hash }, status: 'in progress' })
setCurrentStep({ step, accepted: true })
return yield* handleOnChainConfirmation(params, duplicativeTx.hash)
}
......@@ -139,6 +155,9 @@ function* handleOnChainConfirmation(params: HandleOnChainStepParams, hash: strin
if (interrupt) {
throw new HandledTransactionInterrupt('Transaction flow was interrupted')
}
addTransactionBreadcrumb({ step, data: { txHash: hash }, status: 'complete' })
return hash
}
......@@ -267,3 +286,22 @@ export function getSwapTransactionInfo(trade: ClassicTrade | UniswapXTrade): Swa
}),
}
}
export function addTransactionBreadcrumb({
step,
data = {},
status = 'initiated',
}: {
step: TransactionStep
data?: {
[key: string]: string | number | boolean | undefined
}
status?: 'initiated' | 'complete' | 'in progress' | 'interrupted'
}) {
Sentry.addBreadCrumb({
level: 'info',
category: 'transaction',
message: `${step.type} ${status}`,
data,
})
}
......@@ -21,7 +21,11 @@ export class TransactionStepFailedError extends TransactionError {
step: TransactionStep
isBackendRejection: boolean
originalError?: Error
stringified?: string
// string fields for Sentry
originalErrorStringified?: string
originalErrorString?: string // originalErrorStringified error may get cut off by sentry size limits; this acts as minimal backup
stepStringified?: string
constructor({
message,
......@@ -41,7 +45,9 @@ export class TransactionStepFailedError extends TransactionError {
this.originalError = originalError
try {
this.stringified = JSON.stringify(this, null, 2) // provides more insight to sentry logs
this.originalErrorString = originalError?.toString()
this.originalErrorStringified = JSON.stringify(originalError, null, 2)
this.stepStringified = JSON.stringify(step, null, 2)
} catch {}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment