Skip to content
Open
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
"base-x": "^4.0.0",
"chai": "^4.2.0",
"chai-as-promised": "^7.1.1",
"edge-core-js": "^2.24.0",
"edge-core-js": "^2.43.0",
"esbuild-loader": "^4.1.0",
"eslint": "^7.14.0",
"eslint-config-standard-kit": "0.15.1",
Expand Down
19 changes: 15 additions & 4 deletions src/common/plugin/EngineEmitter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
EdgeCurrencyEngineCallbacks,
EdgeSubscribedAddress,
EdgeTransaction,
EdgeTransactionEvent,
EdgeTxidMap
Expand All @@ -10,9 +11,13 @@ import { SubscribeAddressResponse } from '../utxobased/network/blockbookApi'

export declare interface EngineEmitter {
emit: ((
event: EngineEvent.SEEN_TX_CHECKPOINT,
checkpoint: string
event: EngineEvent.SUBSCRIBE_ADDRESSES,
addresses: EdgeSubscribedAddress[]
) => boolean) &
((
event: EngineEvent.SEEN_TX_CHECKPOINT,
checkpoint: string
) => boolean) &
((
event: EngineEvent.TRANSACTIONS,
transactionEvents: EdgeTransactionEvent[]
Expand Down Expand Up @@ -45,9 +50,13 @@ export declare interface EngineEmitter {
((event: EngineEvent.TXIDS_CHANGED, txids: EdgeTxidMap) => boolean)

on: ((
event: EngineEvent.SEEN_TX_CHECKPOINT,
listener: (checkpoint: string) => Promise<void> | void
event: EngineEvent.SUBSCRIBE_ADDRESSES,
listener: (addresses: EdgeSubscribedAddress[]) => Promise<void> | void
) => this) &
((
event: EngineEvent.SEEN_TX_CHECKPOINT,
listener: (checkpoint: string) => Promise<void> | void
) => this) &
((
event: EngineEvent.TRANSACTIONS,
listener: (
Expand Down Expand Up @@ -95,6 +104,7 @@ export declare interface EngineEmitter {
export class EngineEmitter extends EventEmitter {}

export enum EngineEvent {
SUBSCRIBE_ADDRESSES = 'subscribe:addresses',
SEEN_TX_CHECKPOINT = 'seen:tx:checkpoint',
TRANSACTIONS = 'transactions',
/** @deprecated Use TRANSACTIONS */
Expand Down Expand Up @@ -123,6 +133,7 @@ export const makeEngineEmitter = (
}
)
emitter.on(EngineEvent.SEEN_TX_CHECKPOINT, callbacks.onSeenTxCheckpoint)
emitter.on(EngineEvent.SUBSCRIBE_ADDRESSES, callbacks.onSubscribeAddresses)
emitter.on(EngineEvent.TRANSACTIONS, callbacks.onTransactions)
emitter.on(EngineEvent.TRANSACTIONS_CHANGED, callbacks.onTransactionsChanged)
emitter.on(EngineEvent.TXIDS_CHANGED, callbacks.onTxidsChanged)
Expand Down
41 changes: 41 additions & 0 deletions src/common/utxobased/engine/UtxoEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
DustSpendError,
EdgeCurrencyEngine,
EdgeDataDump,
EdgeEngineSyncNetworkOptions,
EdgeFreshAddress,
EdgeGetReceiveAddressOptions,
EdgeGetTransactionsOptions,
Expand Down Expand Up @@ -61,6 +62,7 @@ import {
pathToPurposeType,
sumUtxos
} from './utils'
import { SubscribeAddressResponse } from '../network/blockbookApi'
import { makeUtxoEngineProcessor } from './UtxoEngineProcessor'
import { makeUtxoWalletTools } from './UtxoWalletTools'

Expand Down Expand Up @@ -1029,6 +1031,45 @@ export async function makeUtxoEngine(
return await sweepTxPromise
},

async syncNetwork(opts: EdgeEngineSyncNetworkOptions): Promise<number> {
const syncIntervalMs = 10000

// If this currency doesn't use the change-server, behave as a normal
// polling engine: just return the polling interval.
if (currencyInfo.usesChangeServer !== true) {
return syncIntervalMs
}

const { subscribeParam } = opts

if (subscribeParam == null) {
// Ordinary polling wakeup — no change-server address activity.
// The existing Blockbook websocket subscriptions handle real-time
// updates; no extra work needed here.
return syncIntervalMs
}

if (subscribeParam.needsSync === false) {
// Core says no real sync is needed for this address.
// Mark addresses-checked at 100% to signal fully synced.
emitter.emit(EngineEvent.ADDRESSES_CHECKED, 1)
return syncIntervalMs
}

// Change-server reported activity for a specific address.
// Feed it into the existing address-scoped processing pipeline by
// emitting NEW_ADDRESS_TRANSACTION — the same event used for direct
// Blockbook address wakeups. The handler only uses response.address,
// so we cast the partial object to satisfy the type signature.
emitter.emit(
EngineEvent.NEW_ADDRESS_TRANSACTION,
'syncNetwork',
{ address: subscribeParam.address } as SubscribeAddressResponse
)

return syncIntervalMs
},

otherMethods: {}
}

Expand Down
33 changes: 33 additions & 0 deletions src/common/utxobased/engine/UtxoEngineProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ export function makeUtxoEngineProcessor(
} = config
const { log } = engineOptions

const { currencyInfo } = pluginInfo
const usesChangeServer = currencyInfo.usesChangeServer === true

const { walletFormats } = walletInfo.keys

const taskCache: TaskCache = {
Expand Down Expand Up @@ -245,12 +248,42 @@ export function makeUtxoEngineProcessor(
running = true

await initializeAddressSubscriptions()

// After initialization, notify core which addresses to subscribe on the
// change-server. Only do this when the currency opts in.
if (usesChangeServer) {
const { subscribedAddresses: restoredAddresses = [] } =
engineOptions
// Build a map of restored checkpoints for fast lookup
const checkpointByAddress = new Map<string, string | undefined>()
for (const entry of restoredAddresses) {
checkpointByAddress.set(entry.address, entry.checkpoint)
}

// Collect all current wallet addresses from the subscribe cache
const addressesToSubscribe = Object.keys(
taskCache.addressSubscribeCache
).map(address => ({
address,
checkpoint: checkpointByAddress.get(address)
}))

if (addressesToSubscribe.length > 0) {
emitter.emit(EngineEvent.SUBSCRIBE_ADDRESSES, addressesToSubscribe)
}
}

await setLookAhead(common)
}

emitter.on(
EngineEvent.BLOCK_HEIGHT_CHANGED,
async (_uri: string, _blockHeight: number): Promise<void> => {
// When change-server is enabled, unconfirmed→confirmed transitions are
// discovered via address wakeups instead of per-block network queries.
// Skip populating transactionUpdateCache to avoid redundant fetchTx calls.
if (usesChangeServer) return

// Add all unconfirmed transactions to the cache to check if these
// transactions have been confirmed:
const txs = await dataLayer.fetchTransactions({
Expand Down
1 change: 1 addition & 0 deletions src/common/utxobased/info/bitcoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const currencyInfo: EdgeCurrencyInfo = {
customFeeTemplate: utxoCustomFeeTemplate,
memoOptions: utxoMemoOptions,
pluginId: 'bitcoin',
usesChangeServer: true,
walletType: 'wallet:bitcoin',

// Explorers:
Expand Down
1 change: 1 addition & 0 deletions src/common/utxobased/info/bitcoincash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const currencyInfo: EdgeCurrencyInfo = {
customFeeTemplate: utxoCustomFeeTemplate,
memoOptions: utxoMemoOptions,
pluginId: 'bitcoincash',
usesChangeServer: true,
walletType: 'wallet:bitcoincash',

// Explorers:
Expand Down
1 change: 1 addition & 0 deletions src/common/utxobased/info/dogecoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const currencyInfo: EdgeCurrencyInfo = {
customFeeTemplate: utxoCustomFeeTemplate,
memoOptions: utxoMemoOptions,
pluginId: 'dogecoin',
usesChangeServer: true,
walletType: 'wallet:dogecoin',

// Explorers:
Expand Down
1 change: 1 addition & 0 deletions src/common/utxobased/info/litecoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const currencyInfo: EdgeCurrencyInfo = {
customFeeTemplate: utxoCustomFeeTemplate,
memoOptions: utxoMemoOptions,
pluginId: 'litecoin',
usesChangeServer: true,
walletType: 'wallet:litecoin',

// Explorers:
Expand Down
2 changes: 2 additions & 0 deletions test/common/utxobased/engine/engine.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ describe('engine.spec', function () {
fakeLogger.info('onTransactionsChanged:', transactionList)
emitter.emit('onTransactionsChanged', transactionList)
},
onSubscribeAddresses() {},
onSyncStatusChanged() {},
onTxidsChanged() {},
onUnactivatedTokenIdsChanged() {},
onWcNewContractCall() {}
Expand Down
24 changes: 15 additions & 9 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,11 @@
"@nodelib/fs.scandir" "2.1.4"
fastq "^1.6.0"

"@nymproject/mix-fetch@^1.4.3":
version "1.4.3"
resolved "https://registry.yarnpkg.com/@nymproject/mix-fetch/-/mix-fetch-1.4.3.tgz#bee246da3f29db6be48fba4e48656f3b1da9cf8b"
integrity sha512-+Q8W2p5JP6T7gk/GSynPabbDHe0hJ+FADTT0VSDQG7rstNSpTvMRz2RjKFuv5+Ufb4ufoEHYhYd8r1l6rrZ/sQ==

"@parcel/fs@^1.11.0":
version "1.11.0"
resolved "https://registry.yarnpkg.com/@parcel/fs/-/fs-1.11.0.tgz#fb8a2be038c454ad46a50dc0554c1805f13535cd"
Expand Down Expand Up @@ -3925,11 +3930,12 @@ ecc-jsbn@~0.1.1:
typeforce "^1.18.0"
wif "^2.0.6"

edge-core-js@^2.24.0:
version "2.24.0"
resolved "https://registry.yarnpkg.com/edge-core-js/-/edge-core-js-2.24.0.tgz#dde491266313562090862510984a85cd5d6659bb"
integrity sha512-MD7U1xrvDeU87xheqfsQOhqovcmBzyNp3j7RAJYtVeG4RDQI/YXXmFlX7QpVooGXJdlbxYsYZiyLVlfnQY9IYQ==
edge-core-js@^2.43.0:
version "2.43.4"
resolved "https://registry.yarnpkg.com/edge-core-js/-/edge-core-js-2.43.4.tgz#8486dce6cf4445934b17c5eaf6954b2425046fd2"
integrity sha512-P+nt44Ijv+gtN3U75bKEG4ylLAT5AE14oaSeoIwid8NLMPM/775UYEzz2FxyIiweJgxzNm6ujBdK4zZURjufzA==
dependencies:
"@nymproject/mix-fetch" "^1.4.3"
aes-js "^3.1.0"
base-x "^4.0.0"
biggystring "^4.2.3"
Expand All @@ -3948,7 +3954,7 @@ edge-core-js@^2.24.0:
scrypt-js "^2.0.3"
serverlet "^0.1.2"
yaob "^0.3.12"
yavent "^0.1.3"
yavent "^0.1.5"

edge-sync-client@^0.2.7, edge-sync-client@^0.2.8:
version "0.2.8"
Expand Down Expand Up @@ -10735,10 +10741,10 @@ yargs@^17.2.1:
y18n "^5.0.5"
yargs-parser "^21.0.0"

yavent@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/yavent/-/yavent-0.1.3.tgz#c86a5e1d013721eda9c732e820fb7d6aaf2ab4db"
integrity sha512-O6ZngnMCkiM1Bg/zP2XKgprjXUuHS0tSQjHxWhMc53avgNu6AT5zcmDm+oYxQLRXQ9ajlEQwQ+Rf7CghKt1u1A==
yavent@^0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/yavent/-/yavent-0.1.5.tgz#caf32af73c59a18142533fddfefd2c0fc8f99b0f"
integrity sha512-VgHZ8Q19exDqdg+sQ4ax3cKfsUvCmeua/nGGPsHeQTfqefQfAMfEk4qwnLE4ABVJhlJOQCfGhxWA3llW6eFk1w==

yocto-queue@^0.1.0:
version "0.1.0"
Expand Down