Skip to content
This repository has been archived by the owner on Apr 11, 2023. It is now read-only.

feat: update subscribeTxs to use new tx parser payloads #266

Merged
merged 8 commits into from
Dec 8, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/chain-adapters/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"type-check": "tsc --project ./tsconfig.json --noEmit"
},
"dependencies": {
"@shapeshiftoss/caip": "^1.5.0",
"axios": "^0.21.2",
"bignumber.js": "^9.0.1",
"bitcoinjs-lib": "^5.2.0",
Expand All @@ -37,7 +38,8 @@
"@shapeshiftoss/hdwallet-core": "^1.18.2",
"@shapeshiftoss/hdwallet-native": "^1.18.2",
"@shapeshiftoss/types": "^1.13.1",
"@shapeshiftoss/unchained-client": "^3.7.0",
"@shapeshiftoss/unchained-client": "^4.0.0",
"@shapeshiftoss/unchained-tx-parser": "^4.0.0",
"bs58check": "^2.0.0"
},
"devDependencies": {
Expand Down
46 changes: 17 additions & 29 deletions packages/chain-adapters/src/bitcoin/BitcoinChainAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import {
accountTypeToOutputScriptType,
accountTypeToScriptType,
convertXpubVersion,
getStatus,
getType,
toPath,
toRootDerivationPath
} from '../utils'
Expand Down Expand Up @@ -413,41 +415,27 @@ export class ChainAdapter implements IChainAdapter<ChainTypes.Bitcoin> {
subscriptionId,
{ topic: 'txs', addresses },
(msg) => {
const status =
msg.confirmations > 0 ? chainAdapters.TxStatus.Confirmed : chainAdapters.TxStatus.Pending

const baseTx = {
const transfers = msg.transfers.map<chainAdapters.TxTransfer>((transfer) => ({
caip19: transfer.caip19,
from: transfer.from,
to: transfer.to,
type: getType(transfer.type),
value: transfer.totalValue
}))

onMessage({
address: msg.address,
asset: ChainTypes.Bitcoin,
blockHash: msg.blockHash,
blockHeight: msg.blockHeight,
blockTime: msg.blockTime,
caip2: msg.caip2,
chain: ChainTypes.Bitcoin,
confirmations: msg.confirmations,
network: NetworkTypes.MAINNET,
txid: msg.txid,
fee: msg.fee,
status
}

// treat all send transfers as same account
if (Object.keys(msg.send).length) {
onMessage({
...baseTx,
chain: ChainTypes.Bitcoin,
type: chainAdapters.TxType.Send,
value: msg.value,
to: msg.vout[0]?.addresses?.[0]
})
}

Object.entries(msg.receive).forEach(([, { totalValue }]) => {
onMessage({
...baseTx,
chain: ChainTypes.Bitcoin,
type: chainAdapters.TxType.Receive,
value: totalValue,
from: msg.vin[0]?.addresses?.[0]
})
status: getStatus(msg.status),
tradeDetails: msg.trade,
transfers,
txid: msg.txid
})
},
(err) => onError({ message: err.message })
Expand Down
121 changes: 29 additions & 92 deletions packages/chain-adapters/src/ethereum/EthereumChainAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Contract } from '@ethersproject/contracts'
import { caip19 } from '@shapeshiftoss/caip'
import { bip32ToAddressNList, ETHSignTx, ETHWallet } from '@shapeshiftoss/hdwallet-core'
import {
BIP32Params,
Expand All @@ -7,16 +8,15 @@ import {
ContractTypes,
NetworkTypes
} from '@shapeshiftoss/types'
import { ethereum, Token } from '@shapeshiftoss/unchained-client'
import { ethereum } from '@shapeshiftoss/unchained-client'
import axios from 'axios'
import BigNumber from 'bignumber.js'
import isEmpty from 'lodash/isEmpty'
import WAValidator from 'multicoin-address-validator'
import { numberToHex } from 'web3-utils'

import { ChainAdapter as IChainAdapter } from '../api'
import { ErrorHandler } from '../error/ErrorHandler'
import { toPath, toRootDerivationPath } from '../utils/bip32'
import { getStatus, getType, toPath, toRootDerivationPath } from '../utils'
import erc20Abi from './erc20Abi.json'

export interface ChainAdapterArgs {
Expand Down Expand Up @@ -297,103 +297,40 @@ export class ChainAdapter implements IChainAdapter<ChainTypes.Ethereum> {
subscriptionId,
{ topic: 'txs', addresses: [address] },
(msg) => {
const getStatus = () => {
const msgStatus = msg.ethereumSpecific?.status

if (msgStatus === -1 && msg.confirmations <= 0) return chainAdapters.TxStatus.Pending
if (msgStatus === 1 && msg.confirmations > 0) return chainAdapters.TxStatus.Confirmed
if (msgStatus === 0) return chainAdapters.TxStatus.Failed

return chainAdapters.TxStatus.Unknown
}
const transfers = msg.transfers.map<chainAdapters.TxTransfer>((transfer) => ({
caip19: transfer.caip19,
from: transfer.from,
to: transfer.to,
type: getType(transfer.type),
value: transfer.totalValue,
chainSpecific: {
...(transfer.token && {
token: {
contract: transfer.token.contract,
contractType:
caip19.fromCAIP19(transfer.caip19).contractType ?? ContractTypes.ERC20,
name: transfer.token.name,
precision: transfer.token.decimals,
symbol: transfer.token.symbol
}
})
}
}))

const baseTx = {
onMessage({
address: msg.address,
blockHash: msg.blockHash,
blockHeight: msg.blockHeight,
blockTime: msg.blockTime,
caip2: msg.caip2,
chain: ChainTypes.Ethereum,
confirmations: msg.confirmations,
network: NetworkTypes.MAINNET,
txid: msg.txid,
fee: msg.fee,
status: getStatus()
}

const specificTx = (symbol: string, value: string, token?: Token) => ({
asset: token?.contract || ChainTypes.Ethereum,
value,
chainSpecific: {
...(token && {
token: {
contract: token.contract,
contractType: ContractTypes.ERC20,
name: token.name,
precision: token.decimals,
symbol
}
})
}
})

if (msg.trade) {
onMessage({
...baseTx,
asset: ChainTypes.Ethereum,
chain: ChainTypes.Ethereum,
value: '0',
chainSpecific: {},
type: chainAdapters.TxType.Trade,
tradeDetails: {
buyAmount: msg.trade.buyAmount,
buyAsset: msg.trade.buyAsset,
dexName: msg.trade.dexName,
feeAmount: msg.trade.feeAmount,
sellAmount: msg.trade.sellAmount,
sellAsset: msg.trade.sellAsset
}
})
}

Object.entries(msg.send).forEach(([symbol, { totalValue, token }]) => {
const tokenTransferTo = msg?.tokenTransfers?.find((transfer) => {
return (
transfer.from === msg.vin[0]?.addresses?.[0] &&
transfer.token === token?.contract &&
transfer.value === totalValue
)
})?.to
onMessage({
...baseTx,
...specificTx(symbol, totalValue, token),
chain: ChainTypes.Ethereum,
type: chainAdapters.TxType.Send,
// For erc20 sends the vout address is the contract
to: tokenTransferTo || msg.vout[0]?.addresses?.[0]
})
})

Object.entries(msg.receive).forEach(([symbol, { totalValue, token }]) => {
onMessage({
...baseTx,
...specificTx(symbol, totalValue, token),
chain: ChainTypes.Ethereum,
type: chainAdapters.TxType.Receive,
from: msg.vin[0]?.addresses?.[0]
})
status: getStatus(msg.status),
tradeDetails: msg.trade,
transfers,
txid: msg.txid
})

// approvals don't have ws data for either send or receive
// but we still need to account for the fees
if (isEmpty(msg.send) && isEmpty(msg.receive)) {
onMessage({
...baseTx,
asset: ChainTypes.Ethereum,
chain: ChainTypes.Ethereum,
value: msg.value,
type: chainAdapters.TxType.Send,
chainSpecific: {}
})
}
},
(err) => onError({ message: err.message })
)
Expand Down
18 changes: 18 additions & 0 deletions packages/chain-adapters/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,20 @@
import { chainAdapters } from '@shapeshiftoss/types'
import { Status, TransferType } from '@shapeshiftoss/unchained-tx-parser'

export * from './bip32'
export * from './utxoUtils'

export const getStatus = (status: Status): chainAdapters.TxStatus => {
if (status === Status.Pending) return chainAdapters.TxStatus.Pending
if (status === Status.Confirmed) return chainAdapters.TxStatus.Confirmed
if (status === Status.Failed) return chainAdapters.TxStatus.Failed

return chainAdapters.TxStatus.Unknown
}

export const getType = (type: TransferType): chainAdapters.TxType => {
if (type === TransferType.Send) return chainAdapters.TxType.Send
if (type === TransferType.Receive) return chainAdapters.TxType.Receive

return chainAdapters.TxType.Unknown
}
4 changes: 0 additions & 4 deletions packages/types/src/chain-adapters/ethereum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ export type TokenWithBalance = Token & {
balance: string
}

export type TxTransfer = {
token?: Token
}

export type FeeData = {
gasPrice: string
gasLimit: string
Expand Down
38 changes: 17 additions & 21 deletions packages/types/src/chain-adapters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,14 @@ export type SubscribeTxsInput = {
}

export type TxFee = {
symbol: string
caip19: string
value: string
}

export enum TxType {
Send = 'send',
Receive = 'receive',
Trade = 'trade'
Unknown = 'unknown'
}

export enum TxStatus {
Expand All @@ -125,37 +125,33 @@ export type SubscribeTxsMessage<T extends ChainTypes> = {
blockHeight: number
blockTime: number
chain: T
caip2: string
confirmations: number
network: NetworkTypes
txid: string
to?: string
from?: string
fee?: TxFee
status: TxStatus
tradeDetails?: TradeDetails
} & TxTransfer<T>
transfers: Array<TxTransfer>
}

export enum TradeType {
Trade = 'trade',
Refund = 'refund'
}

export type TradeDetails = {
buyAmount: string
buyAsset: string
dexName: string
feeAmount: string
sellAmount: string
sellAsset: string
memo?: string
type: TradeType
}

type ChainSpecificTxTransfer<T> = ChainSpecific<
T,
{
[ChainTypes.Ethereum]: ethereum.TxTransfer
}
>

export type TxTransfer<T extends ChainTypes> = {
asset: string
export type TxTransfer = {
caip19: string
from: string
to: string
type: TxType
value: string
} & ChainSpecificTxTransfer<T>
}

export type SubscribeError = {
message: string
Expand Down