ci(release): publish latest release

parent febe0e4b
IPFS hash of the deployment: IPFS hash of the deployment:
- CIDv0: `QmWXkZCZCVea5C5dkKAgH2jR3a8LWCFmJGedqiEaK21wHj` - CIDv0: `QmZ2woTrzL5shcw9Ek6jqsLnHAMh1KGWGPkbeoMw3toRfC`
- CIDv1: `bafybeidzwv7ldnoexuakxu7nxwvkvh7bcku5kxdixe7jdgal36mcur7doi` - CIDv1: `bafybeie645wzgpsz5isxptb3bdyo67rhtc4dfxjekenod6jvf6jxi7yqe4`
The latest release is always mirrored at [app.uniswap.org](https://app.uniswap.org). 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. ...@@ -10,15 +10,10 @@ You can also access the Uniswap Interface from an IPFS gateway.
Your Uniswap settings are never remembered across different URLs. Your Uniswap settings are never remembered across different URLs.
IPFS gateways: IPFS gateways:
- https://bafybeidzwv7ldnoexuakxu7nxwvkvh7bcku5kxdixe7jdgal36mcur7doi.ipfs.dweb.link/ - https://bafybeie645wzgpsz5isxptb3bdyo67rhtc4dfxjekenod6jvf6jxi7yqe4.ipfs.dweb.link/
- https://bafybeidzwv7ldnoexuakxu7nxwvkvh7bcku5kxdixe7jdgal36mcur7doi.ipfs.cf-ipfs.com/ - https://bafybeie645wzgpsz5isxptb3bdyo67rhtc4dfxjekenod6jvf6jxi7yqe4.ipfs.cf-ipfs.com/
- [ipfs://QmWXkZCZCVea5C5dkKAgH2jR3a8LWCFmJGedqiEaK21wHj/](ipfs://QmWXkZCZCVea5C5dkKAgH2jR3a8LWCFmJGedqiEaK21wHj/) - [ipfs://QmZ2woTrzL5shcw9Ek6jqsLnHAMh1KGWGPkbeoMw3toRfC/](ipfs://QmZ2woTrzL5shcw9Ek6jqsLnHAMh1KGWGPkbeoMw3toRfC/)
### 5.51.1 (2024-10-10) ### 5.51.2 (2024-10-10)
### Bug Fixes
* **web:** Cab/web 5130 remove extension launch modal prod (#12891) 07a5a21
web/5.51.1 web/5.51.2
\ No newline at end of file \ No newline at end of file
...@@ -13,4 +13,3 @@ REACT_APP_SENTRY_ENABLED=true ...@@ -13,4 +13,3 @@ REACT_APP_SENTRY_ENABLED=true
REACT_APP_SENTRY_TRACES_SAMPLE_RATE=0.003 REACT_APP_SENTRY_TRACES_SAMPLE_RATE=0.003
REACT_APP_STATSIG_PROXY_URL="https://interface.gateway.uniswap.org/v1/statsig-proxy" REACT_APP_STATSIG_PROXY_URL="https://interface.gateway.uniswap.org/v1/statsig-proxy"
REACT_APP_IS_UNISWAP_INTERFACE=true REACT_APP_IS_UNISWAP_INTERFACE=true
REACT_APP_TRADING_API_KEY=gcZrVL9FxqnqjVytJd2z3oqImkOKRjZ49sF7WXy9
...@@ -11,6 +11,7 @@ import { PopupType, addPopup } from 'state/application/reducer' ...@@ -11,6 +11,7 @@ import { PopupType, addPopup } from 'state/application/reducer'
import { handleUniswapXSignatureStep } from 'state/sagas/transactions/uniswapx' import { handleUniswapXSignatureStep } from 'state/sagas/transactions/uniswapx'
import { import {
HandleOnChainStepParams, HandleOnChainStepParams,
addTransactionBreadcrumb,
getSwapTransactionInfo, getSwapTransactionInfo,
handleApprovalTransactionStep, handleApprovalTransactionStep,
handleOnChainStep, handleOnChainStep,
...@@ -271,8 +272,11 @@ function* uniswapXSwap( ...@@ -271,8 +272,11 @@ function* uniswapXSwap(
} }
function getDisplayableError(error: Error, step: TransactionStep): TransactionError | undefined { 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 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 return undefined
} else if (error instanceof TransactionError) { } else if (error instanceof TransactionError) {
return error // If the error was already formatted as a TransactionError, we just propagate return error // If the error was already formatted as a TransactionError, we just propagate
......
import { formatSwapSignedAnalyticsEventProperties } from 'lib/utils/analytics' import { formatSwapSignedAnalyticsEventProperties } from 'lib/utils/analytics'
import { PopupType, addPopup } from 'state/application/reducer' 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 { addSignature } from 'state/signatures/reducer'
import { SignatureType, UnfilledUniswapXOrderDetails } from 'state/signatures/types' import { SignatureType, UnfilledUniswapXOrderDetails } from 'state/signatures/types'
import { call, put } from 'typed-redux-saga' import { call, put } from 'typed-redux-saga'
...@@ -49,6 +54,8 @@ export function* handleUniswapXSignatureStep(params: HandleUniswapXSignatureStep ...@@ -49,6 +54,8 @@ export function* handleUniswapXSignatureStep(params: HandleUniswapXSignatureStep
throw new HandledTransactionInterrupt('User signed after deadline') throw new HandledTransactionInterrupt('User signed after deadline')
} }
addTransactionBreadcrumb({ step, data: { routing, ...signatureDetails.swapInfo }, status: 'in progress' })
try { try {
yield* call(submitOrder, { signature, quote, routing }) yield* call(submitOrder, { signature, quote, routing })
} catch (error) { } catch (error) {
......
...@@ -36,6 +36,7 @@ import { isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing ...@@ -36,6 +36,7 @@ import { isUniswapX } from 'uniswap/src/features/transactions/swap/utils/routing
import { interruptTransactionFlow } from 'uniswap/src/utils/saga' import { interruptTransactionFlow } from 'uniswap/src/utils/saga'
import { isSameAddress } from 'utilities/src/addresses' import { isSameAddress } from 'utilities/src/addresses'
import { percentFromFloat } from 'utilities/src/format/percent' import { percentFromFloat } from 'utilities/src/format/percent'
import { Sentry } from 'utilities/src/logger/Sentry'
import noop from 'utilities/src/react/noop' import noop from 'utilities/src/react/noop'
import { currencyId } from 'utils/currencyId' import { currencyId } from 'utils/currencyId'
import { signTypedData } from 'utils/signing' import { signTypedData } from 'utils/signing'
...@@ -51,6 +52,15 @@ export function* handleSignatureStep({ setCurrentStep, step, ignoreInterrupt, ac ...@@ -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 // Add a watcher to check if the transaction flow is interrupted during this step
const { throwIfInterrupted } = yield* watchForInterruption(ignoreInterrupt) 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 // Trigger UI prompting user to accept
setCurrentStep({ step, accepted: false }) setCurrentStep({ step, accepted: false })
...@@ -59,6 +69,8 @@ export function* handleSignatureStep({ setCurrentStep, step, ignoreInterrupt, ac ...@@ -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 // If the transaction flow was interrupted, throw an error after the step has completed
yield* call(throwIfInterrupted) yield* call(throwIfInterrupted)
addTransactionBreadcrumb({ step, data: { signature }, status: 'complete' })
return signature return signature
} }
...@@ -81,12 +93,16 @@ export function* handleOnChainStep<T extends OnChainTransactionStep>(params: Han ...@@ -81,12 +93,16 @@ export function* handleOnChainStep<T extends OnChainTransactionStep>(params: Han
const { chainId } = step.txRequest const { chainId } = step.txRequest
const signer = yield* call(getSigner, account.address) 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 // 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) const duplicativeTx = yield* findDuplicativeTx(info, account, chainId, allowDuplicativeTx)
if (duplicativeTx) { if (duplicativeTx) {
if (duplicativeTx.status === TransactionStatus.Confirmed) { if (duplicativeTx.status === TransactionStatus.Confirmed) {
addTransactionBreadcrumb({ step, data: { duplicativeTx: true, hash: duplicativeTx.hash }, status: 'complete' })
return duplicativeTx.hash return duplicativeTx.hash
} else { } else {
addTransactionBreadcrumb({ step, data: { duplicativeTx: true, hash: duplicativeTx.hash }, status: 'in progress' })
setCurrentStep({ step, accepted: true }) setCurrentStep({ step, accepted: true })
return yield* handleOnChainConfirmation(params, duplicativeTx.hash) return yield* handleOnChainConfirmation(params, duplicativeTx.hash)
} }
...@@ -139,6 +155,9 @@ function* handleOnChainConfirmation(params: HandleOnChainStepParams, hash: strin ...@@ -139,6 +155,9 @@ function* handleOnChainConfirmation(params: HandleOnChainStepParams, hash: strin
if (interrupt) { if (interrupt) {
throw new HandledTransactionInterrupt('Transaction flow was interrupted') throw new HandledTransactionInterrupt('Transaction flow was interrupted')
} }
addTransactionBreadcrumb({ step, data: { txHash: hash }, status: 'complete' })
return hash return hash
} }
...@@ -267,3 +286,22 @@ export function getSwapTransactionInfo(trade: ClassicTrade | UniswapXTrade): Swa ...@@ -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 { ...@@ -21,7 +21,11 @@ export class TransactionStepFailedError extends TransactionError {
step: TransactionStep step: TransactionStep
isBackendRejection: boolean isBackendRejection: boolean
originalError?: Error 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({ constructor({
message, message,
...@@ -41,7 +45,9 @@ export class TransactionStepFailedError extends TransactionError { ...@@ -41,7 +45,9 @@ export class TransactionStepFailedError extends TransactionError {
this.originalError = originalError this.originalError = originalError
try { 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 {} } 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