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 all 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
8 changes: 6 additions & 2 deletions packages/chain-adapters/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,21 @@
"web3-utils": "^1.6.0"
},
"peerDependencies": {
"@shapeshiftoss/caip": "^1.5.1",
"@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": {
"@shapeshiftoss/caip": "^1.5.1",
"@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",
"@types/bs58check": "^2.1.0",
"@types/multicoin-address-validator": "^0.5.0"
}
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