Skip to content

Commit

Permalink
Merge branch 'shapeshift:develop' into chainflip-dca
Browse files Browse the repository at this point in the history
  • Loading branch information
CumpsD authored Nov 24, 2024
2 parents b770ae0 + f5b155b commit 77dca75
Show file tree
Hide file tree
Showing 42 changed files with 6,397 additions and 5,125 deletions.
2 changes: 1 addition & 1 deletion .env.base
Original file line number Diff line number Diff line change
Expand Up @@ -175,5 +175,5 @@ REACT_APP_ZERION_BASE_URL=https://api.proxy.shapeshift.com/api/v1/zerion
REACT_APP_ZRX_BASE_URL=https://api.proxy.shapeshift.com/api/v1/zrx/

# chainflip
REACT_APP_CHAINFLIP_API_KEY=6ba154d4-e219-472a-9674-5fa5b1300ccf
REACT_APP_CHAINFLIP_API_KEY=09bc0796ff40435482c0a54fa6ae2784
REACT_APP_CHAINFLIP_API_URL=https://chainflip-broker.io

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

70 changes: 38 additions & 32 deletions packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const CHAIN_ID_TO_BECH32_VAL_PREFIX = {

export const assertIsValidatorAddress = (validator: string, chainId: CosmosSdkChainId) => {
if (CHAIN_ID_TO_BECH32_VAL_PREFIX[chainId] !== bech32.decode(validator).prefix) {
throw new Error(`CosmosSdkBaseAdapter: invalid validator address ${validator}`)
throw new Error(`invalid validator address: ${validator}`)
}
}

Expand Down Expand Up @@ -147,9 +147,7 @@ export abstract class CosmosSdkBaseAdapter<T extends CosmosSdkChainId> implement
}

getBIP44Params({ accountNumber }: GetBIP44ParamsInput): BIP44Params {
if (accountNumber < 0) {
throw new Error('accountNumber must be >= 0')
}
if (accountNumber < 0) throw new Error('accountNumber must be >= 0')
return { ...this.defaultBIP44Params, accountNumber }
}

Expand Down Expand Up @@ -224,13 +222,17 @@ export abstract class CosmosSdkBaseAdapter<T extends CosmosSdkChainId> implement
pubkey: account.pubkey,
} as Account<T>
} catch (err) {
return ErrorHandler(err)
return ErrorHandler(err, {
translation: 'chainAdapters.errors.getAccount',
options: { pubkey },
})
}
}

async getTxHistory(input: TxHistoryInput): Promise<TxHistoryResponse> {
const requestQueue = input.requestQueue ?? new PQueue()
try {
const requestQueue = input.requestQueue ?? new PQueue()

const data = await requestQueue.add(() =>
this.providers.http.getTxHistory({
pubkey: input.pubkey,
Expand Down Expand Up @@ -283,9 +285,7 @@ export abstract class CosmosSdkBaseAdapter<T extends CosmosSdkChainId> implement
})().minus(fee)

if (!availableBalance.isFinite() || availableBalance.lte(0)) {
throw new Error(
`CosmosSdkBaseAdapter: not enough balance to send: ${availableBalance.toString()}`,
)
throw new Error(`not enough balance to send: ${availableBalance.toString()}`)
}

return availableBalance.toString()
Expand Down Expand Up @@ -322,26 +322,41 @@ export abstract class CosmosSdkBaseAdapter<T extends CosmosSdkChainId> implement
receiverAddress,
hex,
}: BroadcastTransactionInput): Promise<string> {
await Promise.all([
assertAddressNotSanctioned(senderAddress),
receiverAddress !== CONTRACT_INTERACTION && assertAddressNotSanctioned(receiverAddress),
])

try {
return this.providers.http.sendTx({ body: { rawTx: hex } })
await Promise.all([
assertAddressNotSanctioned(senderAddress),
receiverAddress !== CONTRACT_INTERACTION && assertAddressNotSanctioned(receiverAddress),
])

const txHash = await this.providers.http.sendTx({ body: { rawTx: hex } })

return txHash
} catch (err) {
return ErrorHandler(err)
if ((err as Error).name === 'ResponseError') {
const response = await ((err as any).response as Response).json()

const match = response.message.match(/description:\s*([^,]+)$/)

return ErrorHandler(JSON.stringify(response), {
translation: 'chainAdapters.errors.broadcastTransactionWithMessage',
options: { message: match && match[1] ? match[1].trim() : response.message },
})
}

return ErrorHandler(err, {
translation: 'chainAdapters.errors.broadcastTransaction',
})
}
}

// eslint-disable-next-line require-await
async validateAddress(address: string): Promise<ValidAddressResult> {
const chain = this.getType()
try {
const chain = this.getType()
const { prefix } = bech32.decode(address)

if (CHAIN_ID_TO_BECH32_ADDR_PREFIX[chain] !== prefix) {
throw new Error(`Invalid address ${address} for ChainId: ${chain}`)
throw new Error(`invalid address ${address} for ${this.getDisplayName()}`)
}

return {
Expand Down Expand Up @@ -386,25 +401,16 @@ export abstract class CosmosSdkBaseAdapter<T extends CosmosSdkChainId> implement
this.providers.ws.close('txs')
}

async getValidators(): Promise<Validator[]> {
if (this.providers.http instanceof unchained.thorchain.V1Api) return []

try {
const data = await this.providers.http.getValidators()
return data.validators.map<Validator>(validator => transformValidator(validator))
} catch (err) {
return ErrorHandler(err)
}
}

async getValidator(address: string): Promise<Validator | undefined> {
if (this.providers.http instanceof unchained.thorchain.V1Api) return

try {
if (this.providers.http instanceof unchained.thorchain.V1Api) return

const validator = await this.providers.http.getValidator({ pubkey: address })
return transformValidator(validator)
} catch (err) {
return ErrorHandler(err)
return ErrorHandler(err, {
translation: 'chainAdapters.errors.getValidator',
})
}
}

Expand Down
160 changes: 97 additions & 63 deletions packages/chain-adapters/src/cosmossdk/cosmos/CosmosChainAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { AssetId } from '@shapeshiftoss/caip'
import { ASSET_REFERENCE, cosmosAssetId } from '@shapeshiftoss/caip'
import type { CosmosSignTx } from '@shapeshiftoss/hdwallet-core'
import type { CosmosSignTx, CosmosWallet, HDWallet } from '@shapeshiftoss/hdwallet-core'
import { supportsCosmos } from '@shapeshiftoss/hdwallet-core'
import type { BIP44Params } from '@shapeshiftoss/types'
import { KnownChainIds } from '@shapeshiftoss/types'
import * as unchained from '@shapeshiftoss/unchained-client'

import { ErrorHandler } from '../../error/ErrorHandler'
import { ChainAdapterError, ErrorHandler } from '../../error/ErrorHandler'
import type {
BuildClaimRewardsTxInput,
BuildDelegateTxInput,
Expand Down Expand Up @@ -71,6 +71,15 @@ export class ChainAdapter extends CosmosSdkBaseAdapter<KnownChainIds.CosmosMainn
this.api = args.providers.http
}

private assertSupportsChain(wallet: HDWallet): asserts wallet is CosmosWallet {
if (!supportsCosmos(wallet)) {
throw new ChainAdapterError(`wallet does not support: ${this.getDisplayName()}`, {
translation: 'chainAdapters.errors.unsupportedChain',
options: { chain: this.getDisplayName() },
})
}
}

getDisplayName() {
return ChainAdapterDisplayName.Cosmos
}
Expand All @@ -89,30 +98,27 @@ export class ChainAdapter extends CosmosSdkBaseAdapter<KnownChainIds.CosmosMainn
}

async getAddress(input: GetAddressInput): Promise<string> {
const { accountNumber, pubKey, wallet, showOnDevice = false } = input
try {
const { accountNumber, pubKey, wallet, showOnDevice = false } = input

if (pubKey) return pubKey
if (pubKey) return pubKey

try {
if (supportsCosmos(wallet)) {
await verifyLedgerAppOpen(this.chainId, wallet)

const bip44Params = this.getBIP44Params({ accountNumber })
const cosmosAddress = await wallet.cosmosGetAddress({
addressNList: toAddressNList(bip44Params),
showDisplay: showOnDevice,
})

if (!cosmosAddress) {
throw new Error('Unable to generate Cosmos address.')
}

return cosmosAddress
} else {
throw new Error('Wallet does not support Cosmos.')
}
} catch (error) {
return ErrorHandler(error)
this.assertSupportsChain(wallet)
await verifyLedgerAppOpen(this.chainId, wallet)

const bip44Params = this.getBIP44Params({ accountNumber })
const address = await wallet.cosmosGetAddress({
addressNList: toAddressNList(bip44Params),
showDisplay: showOnDevice,
})

if (!address) throw new Error('error getting address from wallet')

return address
} catch (err) {
return ErrorHandler(err, {
translation: 'chainAdapters.errors.getAddress',
})
}
}

Expand All @@ -139,16 +145,27 @@ export class ChainAdapter extends CosmosSdkBaseAdapter<KnownChainIds.CosmosMainn

return this.buildTransaction({ ...input, account, msg })
} catch (err) {
return ErrorHandler(err)
return ErrorHandler(err, {
translation: 'chainAdapters.errors.buildTransaction',
})
}
}

async buildSendTransaction(
input: BuildSendTxInput<KnownChainIds.CosmosMainnet>,
): Promise<{ txToSign: CosmosSignTx }> {
const { accountNumber, wallet } = input
const from = await this.getAddress({ accountNumber, wallet })
return this.buildSendApiTransaction({ ...input, from })
try {
const { accountNumber, wallet } = input

const from = await this.getAddress({ accountNumber, wallet })
const tx = await this.buildSendApiTransaction({ ...input, from })

return tx
} catch (err) {
return ErrorHandler(err, {
translation: 'chainAdapters.errors.buildTransaction',
})
}
}

async buildDelegateTransaction(
Expand Down Expand Up @@ -178,7 +195,9 @@ export class ChainAdapter extends CosmosSdkBaseAdapter<KnownChainIds.CosmosMainn

return this.buildTransaction({ ...tx, account, msg })
} catch (err) {
return ErrorHandler(err)
return ErrorHandler(err, {
translation: 'chainAdapters.errors.buildTransaction',
})
}
}

Expand Down Expand Up @@ -209,7 +228,9 @@ export class ChainAdapter extends CosmosSdkBaseAdapter<KnownChainIds.CosmosMainn

return this.buildTransaction({ ...tx, account, msg })
} catch (err) {
return ErrorHandler(err)
return ErrorHandler(err, {
translation: 'chainAdapters.errors.buildTransaction',
})
}
}

Expand Down Expand Up @@ -243,7 +264,9 @@ export class ChainAdapter extends CosmosSdkBaseAdapter<KnownChainIds.CosmosMainn

return this.buildTransaction({ ...tx, account, msg })
} catch (err) {
return ErrorHandler(err)
return ErrorHandler(err, {
translation: 'chainAdapters.errors.buildTransaction',
})
}
}

Expand All @@ -268,40 +291,48 @@ export class ChainAdapter extends CosmosSdkBaseAdapter<KnownChainIds.CosmosMainn

return this.buildTransaction({ ...tx, account, msg })
} catch (err) {
return ErrorHandler(err)
return ErrorHandler(err, {
translation: 'chainAdapters.errors.buildTransaction',
})
}
}

async signTransaction(signTxInput: SignTxInput<CosmosSignTx>): Promise<string> {
try {
const { txToSign, wallet } = signTxInput
if (supportsCosmos(wallet)) {
await verifyLedgerAppOpen(this.chainId, wallet)

const signedTx = await wallet.cosmosSignTx(txToSign)
this.assertSupportsChain(wallet)
await verifyLedgerAppOpen(this.chainId, wallet)

if (!signedTx?.serialized) throw new Error('Error signing tx')
const signedTx = await wallet.cosmosSignTx(txToSign)

return signedTx.serialized
} else {
throw new Error('Wallet does not support Cosmos.')
}
if (!signedTx?.serialized) throw new Error('error signing tx')

return signedTx.serialized
} catch (err) {
return ErrorHandler(err)
return ErrorHandler(err, {
translation: 'chainAdapters.errors.signTransaction',
})
}
}

async getFeeData(
_: Partial<GetFeeDataInput<KnownChainIds.CosmosMainnet>>,
): Promise<FeeDataEstimate<KnownChainIds.CosmosMainnet>> {
const gasLimit = '2000000'
const fees = await this.api.fees()
const txFee = bnOrZero(fees[Denoms.uatom]).times(gasLimit).toFixed(0)

return {
fast: { txFee, chainSpecific: { gasLimit } },
average: { txFee, chainSpecific: { gasLimit } },
slow: { txFee, chainSpecific: { gasLimit } },
try {
const gasLimit = '2000000'
const fees = await this.api.fees()
const txFee = bnOrZero(fees[Denoms.uatom]).times(gasLimit).toFixed(0)

return {
fast: { txFee, chainSpecific: { gasLimit } },
average: { txFee, chainSpecific: { gasLimit } },
slow: { txFee, chainSpecific: { gasLimit } },
}
} catch (err) {
return ErrorHandler(err, {
translation: 'chainAdapters.errors.getFeeData',
})
}
}

Expand All @@ -310,21 +341,24 @@ export class ChainAdapter extends CosmosSdkBaseAdapter<KnownChainIds.CosmosMainn
receiverAddress,
signTxInput,
}: SignAndBroadcastTransactionInput<KnownChainIds.CosmosMainnet>): Promise<string> {
await Promise.all([
assertAddressNotSanctioned(senderAddress),
receiverAddress !== CONTRACT_INTERACTION && assertAddressNotSanctioned(receiverAddress),
])

const { wallet } = signTxInput
try {
if (supportsCosmos(wallet)) {
const signedTx = await this.signTransaction(signTxInput)
return this.providers.http.sendTx({ body: { rawTx: signedTx } })
} else {
throw new Error('Wallet does not support Cosmos.')
}
} catch (error) {
return ErrorHandler(error)
const { wallet } = signTxInput

await Promise.all([
assertAddressNotSanctioned(senderAddress),
receiverAddress !== CONTRACT_INTERACTION && assertAddressNotSanctioned(receiverAddress),
])

this.assertSupportsChain(wallet)

const hex = await this.signTransaction(signTxInput)
const txHash = await this.broadcastTransaction({ senderAddress, receiverAddress, hex })

return txHash
} catch (err) {
return ErrorHandler(err, {
translation: 'chainAdapters.errors.signAndBroadcastTransaction',
})
}
}
}
Loading

0 comments on commit 77dca75

Please sign in to comment.