Skip to content

Commit

Permalink
Merge pull request #619 from EdgeApp/sam/fil-network-query
Browse files Browse the repository at this point in the history
- fixed: Filecoin network fee query issue
- changed: Use Filfox exclusively for Filecoin transaction querying
  • Loading branch information
samholmes authored Sep 8, 2023
2 parents 9351e32 + 4d95709 commit 2367cfb
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 71 deletions.
157 changes: 87 additions & 70 deletions src/filecoin/FilecoinEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import {
FilecoinWalletOtherData,
SafeFilecoinWalletInfo
} from './filecoinTypes'
import { Filfox, FilfoxMessage } from './Filfox'
import { Filfox, FilfoxMessageDetailed } from './Filfox'
import { Filscan, FilscanMessage } from './Filscan'
import { RpcExtra } from './RpcExtra'

Expand All @@ -48,6 +48,7 @@ export class FilecoinEngine extends CurrencyEngine<
> {
address: Address
availableAttoFil: string
isScanning: boolean
networkInfo: FilecoinNetworkInfo
otherData!: FilecoinWalletOtherData
pluginId: string
Expand All @@ -68,26 +69,25 @@ export class FilecoinEngine extends CurrencyEngine<
const { networkInfo } = env
this.address = Address.fromString(walletInfo.keys.address)
this.availableAttoFil = '0'
this.isScanning = false
this.networkInfo = networkInfo
this.pluginId = this.currencyInfo.pluginId

this.filRpc = new RPC(env.networkInfo.rpcNode.networkName, {
url: env.networkInfo.rpcNode.url,
token: env.currencyInfo.currencyCode
})
this.filfoxApi = new Filfox(env.networkInfo.filfoxUrl, env.io.fetchCors)
this.filscanApi = new Filscan(env.networkInfo.filscanUrl, env.io.fetchCors)
this.rpcExtra = new RpcExtra(env.networkInfo.rpcNode.url, env.io.fetchCors)

this.networkInfo = networkInfo
this.pluginId = this.currencyInfo.pluginId
}

setOtherData(raw: any): void {
this.otherData = asFilecoinWalletOtherData(raw)
}

initData(): void {
// Initialize walletLocalData:
// ...

this.tokenCheckTransactionsStatus[this.currencyInfo.currencyCode] = 0
// Engine variables
this.availableAttoFil = '0'
}
Expand Down Expand Up @@ -299,52 +299,71 @@ export class FilecoinEngine extends CurrencyEngine<
}

async checkTransactions(): Promise<void> {
const addressString = this.address.toString()

const handleScanProgress = (progress: number): void => {
const currentProgress =
this.tokenCheckTransactionsStatus[this.currencyInfo.currencyCode]
const newProgress = progress

if (
// Only send event if we haven't completed sync
currentProgress < 1 &&
// Avoid thrashing
(newProgress >= 1 || newProgress > currentProgress * 1.1)
) {
this.tokenCheckTransactionsStatus[this.currencyInfo.currencyCode] =
newProgress
this.updateOnAddressesChecked()
// We shouldn't start scanning if scanning is already happening:
if (this.isScanning) return
try {
this.isScanning = true

const addressString = this.address.toString()

const handleScanProgress = (progress: number): void => {
const currentProgress =
this.tokenCheckTransactionsStatus[this.currencyInfo.currencyCode]
const newProgress = progress

if (
// Only send event if we haven't completed sync
currentProgress < 1 &&
// Avoid thrashing
(newProgress >= 1 || newProgress > currentProgress * 1.1)
) {
this.tokenCheckTransactionsStatus[this.currencyInfo.currencyCode] =
newProgress
this.updateOnAddressesChecked()
}
}
}

const handleScan = ({
tx,
progress
}: {
tx: EdgeTransaction
progress: number
}): void => {
this.addTransaction(this.currencyInfo.currencyCode, tx)
this.onUpdateTransactions()

// Progress the block-height if the message's height is greater than
// last poll for block-height.
if (this.walletLocalData.blockHeight < tx.blockHeight) {
this.onUpdateBlockHeight(tx.blockHeight)
const handleScan = ({
tx,
progress
}: {
tx: EdgeTransaction
progress: number
}): void => {
this.addTransaction(this.currencyInfo.currencyCode, tx)
this.onUpdateTransactions()

// Progress the block-height if the message's height is greater than
// last poll for block-height.
if (this.walletLocalData.blockHeight < tx.blockHeight) {
this.onUpdateBlockHeight(tx.blockHeight)
}

handleScanProgress(progress)
}

handleScanProgress(progress)
}
const scanners = [
// this.scanTransactionsFromFilscan(addressString, handleScan),
this.scanTransactionsFromFilfox(addressString, handleScan)
]

const scanners = [
this.scanTransactionsFromFilscan(addressString, handleScan),
this.scanTransactionsFromFilfox(addressString, handleScan)
]
const startingNetworkHeight = this.walletLocalData.blockHeight

await Promise.all(scanners)
// Run scanners:
await Promise.all(scanners)

handleScanProgress(1)
// Save the network height at the start of the scanning
this.walletLocalData.lastAddressQueryHeight = startingNetworkHeight
this.walletLocalDataDirty = true

// Make sure the sync progress is 100%
handleScanProgress(1)
} catch (error) {
console.error(error)
throw error
} finally {
this.isScanning = false
}
}

async scanTransactionsFromFilfox(
Expand All @@ -369,17 +388,14 @@ export class FilecoinEngine extends CurrencyEngine<

const messages = messagesResponse.messages
for (const message of messages) {
const txid = message.cid
const idx = this.findTransaction(this.currencyInfo.currencyCode, txid)

if (idx >= 0) {
// Exit early because we reached transaction history from previous
// check
return
}
// Exit when we reach a transaction we may already have saved
if (message.height < this.walletLocalData.lastAddressQueryHeight) return

// Process message into a transaction
const tx = this.filfoxMessageToEdgeTransaction(message)
const messageDetails = await this.filfoxApi.getMessageDetails(
message.cid
)
const tx = this.filfoxMessageToEdgeTransaction(messageDetails)

// Calculate the progress
const progress =
Expand Down Expand Up @@ -412,14 +428,8 @@ export class FilecoinEngine extends CurrencyEngine<

const messages = messagesResponse.messages_by_account_id_list
for (const message of messages) {
const txid = message.cid
const idx = this.findTransaction(this.currencyInfo.currencyCode, txid)

if (idx >= 0) {
// Exit early because we reached transaction history from previous
// check
return
}
// Exit when we reach a transaction we may already have saved
if (message.height < this.walletLocalData.lastAddressQueryHeight) return

// Process message into a transaction
const tx = this.filscanMessageToEdgeTransaction(message)
Expand All @@ -434,25 +444,32 @@ export class FilecoinEngine extends CurrencyEngine<
}

filfoxMessageToEdgeTransaction = (
message: FilfoxMessage
messageDetails: FilfoxMessageDetailed
): EdgeTransaction => {
const addressString = this.address.toString()
let netNativeAmount = message.value
let netNativeAmount = messageDetails.value
const ourReceiveAddresses = []

const networkFee = '0' // TODO: calculate transaction fee from onchain gas fields
if (message.to !== addressString) {
// Get the fees paid
const networkFee = messageDetails.transfers
.filter(
transfer =>
transfer.type === 'miner-fee' || transfer.type === 'burner-fee'
)
.reduce((sum, transfer) => add(sum, transfer.value), '0')

if (messageDetails.to !== addressString) {
// check if tx is a spend
netNativeAmount = `-${add(netNativeAmount, networkFee)}`
} else {
ourReceiveAddresses.push(addressString)
}

const edgeTransaction: EdgeTransaction = {
txid: message.cid,
date: message.timestamp,
txid: messageDetails.cid,
date: messageDetails.timestamp,
currencyCode: this.currencyInfo.currencyCode,
blockHeight: message.height,
blockHeight: messageDetails.height,
nativeAmount: netNativeAmount,
isSend: netNativeAmount.startsWith('-'),
networkFee,
Expand Down
69 changes: 68 additions & 1 deletion src/filecoin/Filfox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,50 @@ export const asFilfoxMessage = asObject({
height: asNumber,
method: asString,
nonce: asNumber,
reciept: asObject({
receipt: asObject({
exitCode: asNumber
}),
timestamp: asNumber,
to: asString,
value: asString
})

export type FilfoxMessageDetailed = ReturnType<typeof asFilfoxMessageDetailed>
export const asFilfoxMessageDetailed = asObject({
cid: asString,
height: asNumber,
timestamp: asNumber,
from: asString,
to: asString,
value: asString,
gasLimit: asNumber,
gasFeeCap: asString,
gasPremium: asString,
receipt: asObject({
exitCode: asNumber,
return: asString,
gasUsed: asNumber
}),
baseFee: asString,
fee: asObject({
baseFeeBurn: asString,
overEstimationBurn: asString,
minerPenalty: asString,
minerTip: asString,
refund: asString
}),
transfers: asArray(
asObject({
from: asString,
fromId: asString,
to: asString,
toId: asString,
value: asString,
type: asString
})
)
})

//
// Messages
//
Expand All @@ -58,6 +94,15 @@ export const asFilfoxMessagesResult = asObject({
totalCount: asNumber
})

//
// Message Details
//

export type FilfoxMessageDetailsResult = ReturnType<
typeof asFilfoxMessageDetailsResult
>
export const asFilfoxMessageDetailsResult = asFilfoxMessageDetailed

// -----------------------------------------------------------------------------
// Implementation
// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -98,4 +143,26 @@ export class Filfox {

return responseBody
}

async getMessageDetails(
messageCid: string
): Promise<FilfoxMessageDetailsResult> {
const response = await this.fetch(`${this.baseUrl}/message/${messageCid}`, {
method: 'GET',
headers: {
'content-type': 'application/json'
}
})
const responseText = await response.text()
const responseBody = asFilfoxEnvelope(asFilfoxMessageDetailsResult)(
responseText
)

if ('error' in responseBody)
throw new Error(
`Error response code ${responseBody.statusCode}: ${responseBody.message} ${responseBody.error}`
)

return responseBody
}
}

0 comments on commit 2367cfb

Please sign in to comment.