From 9d779e94db0ece0c01489abb9c1c8ac46fa60068 Mon Sep 17 00:00:00 2001 From: lbqds Date: Wed, 22 May 2024 19:59:43 +0800 Subject: [PATCH 1/7] Simplify subscription --- packages/web3/src/contract/contract.ts | 8 ++++---- packages/web3/src/contract/events.ts | 16 ++-------------- packages/web3/src/utils/subscription.ts | 4 ++-- test/events.test.ts | 7 ++----- test/exchange.test.ts | 1 - 5 files changed, 10 insertions(+), 26 deletions(-) diff --git a/packages/web3/src/contract/contract.ts b/packages/web3/src/contract/contract.ts index 0cb6b37b5..437d02216 100644 --- a/packages/web3/src/contract/contract.ts +++ b/packages/web3/src/contract/contract.ts @@ -1831,14 +1831,14 @@ export function subscribeEventsFromContract M, fromCount?: number ): EventSubscription { - const messageCallback = (event: node.ContractEvent): Promise => { + const messageCallback = (event: node.ContractEvent) => { if (event.eventIndex !== eventIndex) { return Promise.resolve() } return options.messageCallback(decodeFunc(event)) } - const errorCallback = (err: any, subscription: Subscription): Promise => { + const errorCallback = (err: any, subscription: Subscription) => { return options.errorCallback(err, subscription as unknown as Subscription) } const opt: EventSubscribeOptions = { @@ -2271,13 +2271,13 @@ export function subscribeContractEvents( options: EventSubscribeOptions>, fromCount?: number ): EventSubscription { - const messageCallback = (event: node.ContractEvent): Promise => { + const messageCallback = (event: node.ContractEvent) => { return options.messageCallback({ ...decodeEvent(contract, instance, event, event.eventIndex), contractAddress: instance.address }) } - const errorCallback = (err: any, subscription: Subscription): Promise => { + const errorCallback = (err: any, subscription: Subscription) => { return options.errorCallback(err, subscription as unknown as Subscription>) } const opt: EventSubscribeOptions = { diff --git a/packages/web3/src/contract/events.ts b/packages/web3/src/contract/events.ts index 976006dd5..c3879db74 100644 --- a/packages/web3/src/contract/events.ts +++ b/packages/web3/src/contract/events.ts @@ -21,13 +21,13 @@ import { node } from '../api' import { Subscription, SubscribeOptions } from '../utils' export interface EventSubscribeOptions extends SubscribeOptions { - onEventCountChanged?: (eventCount: number) => Promise + onEventCountChanged?: (eventCount: number) => Promise | void } export class EventSubscription extends Subscription { readonly contractAddress: string private fromCount: number - private onEventCountChanged?: (eventCount: number) => Promise + private onEventCountChanged?: (eventCount: number) => Promise | void constructor(options: EventSubscribeOptions, contractAddress: string, fromCount?: number) { super(options) @@ -38,13 +38,6 @@ export class EventSubscription extends Subscription { this.startPolling() } - override startPolling(): void { - this.eventEmitter.on('tick', async () => { - await this.polling() - }) - this.eventEmitter.emit('tick') - } - currentEventCount(): number { return this.fromCount } @@ -54,12 +47,7 @@ export class EventSubscription extends Subscription { const events = await web3.getCurrentNodeProvider().events.getEventsContractContractaddress(this.contractAddress, { start: this.fromCount }) - if (this.cancelled) { - return - } - if (this.fromCount === events.nextStart) { - this.task = setTimeout(() => this.eventEmitter.emit('tick'), this.pollingInterval) return } diff --git a/packages/web3/src/utils/subscription.ts b/packages/web3/src/utils/subscription.ts index 55fc972d8..f9f585221 100644 --- a/packages/web3/src/utils/subscription.ts +++ b/packages/web3/src/utils/subscription.ts @@ -18,8 +18,8 @@ along with the library. If not, see . import EventEmitter from 'eventemitter3' -type MessageCallback = (message: Message) => Promise -type ErrorCallback = (error: any, subscription: Subscription) => Promise +type MessageCallback = (message: Message) => Promise | void +type ErrorCallback = (error: any, subscription: Subscription) => Promise | void export interface SubscribeOptions { pollingInterval: number diff --git a/test/events.test.ts b/test/events.test.ts index ba37d4e4b..122451367 100644 --- a/test/events.test.ts +++ b/test/events.test.ts @@ -58,18 +58,15 @@ describe('events', function () { function createSubscribeOptions(events: Array): EventSubscribeOptions { return { pollingInterval: 500, - messageCallback: (event: T): Promise => { + messageCallback: (event: T) => { events.push(event) - return Promise.resolve() }, - errorCallback: (error: any, subscription): Promise => { + errorCallback: (error: any, subscription) => { console.log(error) subscription.unsubscribe() - return Promise.resolve() }, onEventCountChanged: (count: number) => { eventCount = count - return Promise.resolve() } } } diff --git a/test/exchange.test.ts b/test/exchange.test.ts index d9dc2325e..b4cf8840c 100644 --- a/test/exchange.test.ts +++ b/test/exchange.test.ts @@ -120,7 +120,6 @@ class BlockPoller extends Subscription { messageCallback: callback, errorCallback: (err) => { console.error(err) - return Promise.resolve() } }) this.nodeProvider = nodeProvider From 2188ac00fe6f3b4d5b287faa063a4538c4b682ce Mon Sep 17 00:00:00 2001 From: lbqds Date: Wed, 22 May 2024 21:54:00 +0800 Subject: [PATCH 2/7] Add block subscription --- packages/web3/src/utils/block.test.ts | 158 ++++++++++++++++++++++++++ packages/web3/src/utils/block.ts | 141 +++++++++++++++++++++++ packages/web3/src/utils/index.ts | 1 + 3 files changed, 300 insertions(+) create mode 100644 packages/web3/src/utils/block.test.ts create mode 100644 packages/web3/src/utils/block.ts diff --git a/packages/web3/src/utils/block.test.ts b/packages/web3/src/utils/block.test.ts new file mode 100644 index 000000000..f2c61f66e --- /dev/null +++ b/packages/web3/src/utils/block.test.ts @@ -0,0 +1,158 @@ +/* +Copyright 2018 - 2022 The Alephium Authors +This file is part of the alephium project. + +The library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the library. If not, see . +*/ + +import { BlockSubscribeOptions, BlockSubscriptionBase, ReorgCallback } from './block' +import * as node from '../api/api-alephium' +import { TOTAL_NUMBER_OF_GROUPS } from '../constants' +import { randomInt } from 'crypto' + +describe('block subscription', function () { + let fromGroup: number + let toGroup: number + let orphanHashes: string[] = [] + let newHashes: string[] = [] + let options: BlockSubscribeOptions + + beforeEach(() => { + fromGroup = randomInt(0, TOTAL_NUMBER_OF_GROUPS) + toGroup = randomInt(0, TOTAL_NUMBER_OF_GROUPS) + orphanHashes = [] + newHashes = [] + options = { + pollingInterval: 0, + messageCallback: () => { + return + }, + errorCallback: () => { + return + }, + reorgCallback: (orphans, newBlocks) => { + orphanHashes.push(...orphans.map((b) => b.hash)) + newHashes.push(...newBlocks.map((b) => b.hash)) + } + } + }) + + it('should handle reorg(1 orphan block)', async () => { + const chains = [ + ['common', 'main-0'], + ['common', 'fork-0'] + ] + const blockSubscription = new BlockSubscriptionTest(options, fromGroup, toGroup, chains) + await blockSubscription.handleReorgForTest('fork-0', 1) + expect(orphanHashes).toEqual(['fork-0']) + expect(newHashes).toEqual(['main-0']) + }) + + it('should handle reorg(multiple orphan blocks)', async () => { + const chains = [ + ['common', 'main-0', 'main-1', 'main-2', 'main-3'], + ['common', 'fork-0', 'fork-1', 'fork-2'] + ] + const blockSubscription = new BlockSubscriptionTest(options, fromGroup, toGroup, chains) + await blockSubscription.handleReorgForTest('fork-2', 3) + expect(orphanHashes).toEqual(['fork-0', 'fork-1', 'fork-2']) + expect(newHashes).toEqual(['main-0', 'main-1', 'main-2']) + }) + + function buildHashesByHeightMap(chains: string[][]) { + const hashesByHeight: Map = new Map() + const sortedChains = chains.sort((a, b) => { + if (a.length === b.length) { + return b[b.length - 1] > a[a.length - 1] ? 1 : -1 + } + return b.length - a.length + }) + const maxHeight = sortedChains[0].length + for (let currentHeight = 0; currentHeight < maxHeight; currentHeight += 1) { + const hashes = hashesByHeight.get(currentHeight) ?? [] + sortedChains + .filter((c) => c.length > currentHeight) + .forEach((c) => { + if (!hashes.includes(c[currentHeight])) { + hashes.push(c[currentHeight]) + } + hashesByHeight.set(currentHeight, hashes) + }) + } + return hashesByHeight + } + + function buildBlockByHashMap(chains: string[][], fromGroup: number, toGroup: number) { + const blockByHash: Map = new Map() + for (const chain of chains) { + for (let index = 0; index < chain.length; index += 1) { + const hash = chain[index] + const parentHash = index === 0 ? 'undefined' : chain[index - 1] + const depsLength = TOTAL_NUMBER_OF_GROUPS * 2 - 1 + const deps = Array.from(Array(depsLength).keys()).map(() => '') + const parentIndex = Math.floor(depsLength / 2) + toGroup + deps[parentIndex] = parentHash + const blockEntry: node.BlockEntry = { + hash: hash, + timestamp: 0, + chainFrom: fromGroup, + chainTo: toGroup, + height: index, + deps, + transactions: [], + nonce: '', + version: 0, + depStateHash: '', + txsHash: '', + target: '' + } + blockByHash.set(hash, blockEntry) + } + } + return blockByHash + } + + class BlockSubscriptionTest extends BlockSubscriptionBase { + readonly fromGroup: number + readonly toGroup: number + readonly onReorgCallback?: ReorgCallback + readonly hashesByHeight: Map + readonly blockByHash: Map + + override getHashesAtHeight(height: number): Promise { + return Promise.resolve(this.hashesByHeight.get(height)!) + } + + override getBlockByHash(hash: string): Promise { + return Promise.resolve(this.blockByHash.get(hash)!) + } + + override polling(): Promise { + return Promise.resolve() + } + + async handleReorgForTest(fromHash: string, fromHeight: number) { + await this.handleReorg(fromHash, fromHeight) + } + + constructor(options: BlockSubscribeOptions, fromGroup: number, toGroup: number, chains: string[][]) { + super(options) + this.fromGroup = fromGroup + this.toGroup = toGroup + this.onReorgCallback = options.reorgCallback + this.hashesByHeight = buildHashesByHeightMap(chains) + this.blockByHash = buildBlockByHashMap(chains, fromGroup, toGroup) + } + } +}) diff --git a/packages/web3/src/utils/block.ts b/packages/web3/src/utils/block.ts new file mode 100644 index 000000000..4f2965b2b --- /dev/null +++ b/packages/web3/src/utils/block.ts @@ -0,0 +1,141 @@ +/* +Copyright 2018 - 2022 The Alephium Authors +This file is part of the alephium project. + +The library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the library. If not, see . +*/ + +import { Subscription, SubscribeOptions } from './subscription' +import * as node from '../api/api-alephium' +import { NodeProvider } from '../api' +import * as web3 from '../global' + +export type ReorgCallback = (orphanBlocks: node.BlockEntry[], newBlocks: node.BlockEntry[]) => Promise | void + +export interface BlockSubscribeOptions extends SubscribeOptions { + reorgCallback?: ReorgCallback +} + +export abstract class BlockSubscriptionBase extends Subscription { + abstract readonly onReorgCallback?: ReorgCallback + abstract readonly fromGroup: number + abstract readonly toGroup: number + + abstract getHashesAtHeight(height: number): Promise + abstract getBlockByHash(hash: string): Promise + + protected getParentHash(block: node.BlockEntry): string { + const index = Math.floor(block.deps.length / 2) + this.toGroup + return block.deps[index] + } + + protected async handleReorg(blockHash: string, blockHeight: number) { + console.log(`reorg occur, hash: ${blockHash}, height: ${blockHeight}`) + if (this.onReorgCallback === undefined) return + + const orphans: string[] = [] + const newHashes: string[] = [] + let fromHash = blockHash + let fromHeight = blockHeight + while (true) { + const hashes = await this.getHashesAtHeight(fromHeight) + const canonicalHash = hashes[0] + if (canonicalHash !== fromHash) { + orphans.push(fromHash) + newHashes.push(canonicalHash) + const block = await this.getBlockByHash(fromHash) + fromHash = this.getParentHash(block) + fromHeight -= 1 + } else { + break + } + } + + const orphanBlocks: node.BlockEntry[] = [] + for (const hash of orphans.reverse()) { + const block = await this.getBlockByHash(hash) + orphanBlocks.push(block) + } + + const newBlocks: node.BlockEntry[] = [] + for (const hash of newHashes.reverse()) { + const block = await this.getBlockByHash(hash) + newBlocks.push(block) + } + console.info(`orphan hashes: ${orphanBlocks.map((b) => b.hash)}, new hashes: ${newBlocks.map((b) => b.hash)}`) + await this.onReorgCallback(orphanBlocks, newBlocks) + } +} + +export class BlockSubscription extends BlockSubscriptionBase { + readonly nodeProvider: NodeProvider + readonly fromGroup: number + readonly toGroup: number + readonly onReorgCallback?: ReorgCallback + private currentBlockHeight: number + private parentBlockHash: string | undefined + + constructor( + options: BlockSubscribeOptions, + fromGroup: number, + toGroup: number, + fromBlockHeight: number, + nodeProvider: NodeProvider | undefined = undefined + ) { + super(options) + this.nodeProvider = nodeProvider ?? web3.getCurrentNodeProvider() + this.fromGroup = fromGroup + this.toGroup = toGroup + this.onReorgCallback = options.reorgCallback + this.currentBlockHeight = fromBlockHeight + this.parentBlockHash = undefined + + this.startPolling() + } + + override async getHashesAtHeight(height: number): Promise { + const result = await this.nodeProvider.blockflow.getBlockflowHashes({ + fromGroup: this.fromGroup, + toGroup: this.toGroup, + height + }) + return result.headers + } + + override async getBlockByHash(hash: string): Promise { + return await this.nodeProvider.blockflow.getBlockflowBlocksBlockHash(hash) + } + + override async polling(): Promise { + try { + const chainInfo = await this.nodeProvider.blockflow.getBlockflowChainInfo({ + fromGroup: this.fromGroup, + toGroup: this.toGroup + }) + + while (this.currentBlockHeight <= chainInfo.currentHeight) { + const hashes = await this.getHashesAtHeight(this.currentBlockHeight) + const block = await this.getBlockByHash(hashes[0]) + if (this.parentBlockHash !== undefined && this.getParentHash(block) !== this.parentBlockHash) { + await this.handleReorg(this.parentBlockHash, this.currentBlockHeight - 1) + } + await this.messageCallback(block) + this.currentBlockHeight += 1 + this.parentBlockHash = hashes[0] + } + } catch (err) { + await this.errorCallback(err, this) + } + } +} diff --git a/packages/web3/src/utils/index.ts b/packages/web3/src/utils/index.ts index d11ecba64..46a3356ec 100644 --- a/packages/web3/src/utils/index.ts +++ b/packages/web3/src/utils/index.ts @@ -25,3 +25,4 @@ export * from './subscription' export * from './sign' export * from './number' export { validateExchangeAddress, isALPHTransferTx, getSenderAddress, getALPHDepositInfo } from './exchange' +export { ReorgCallback, BlockSubscribeOptions, BlockSubscription } from './block' From 09627756f8f5fcce9c2f9826a732ca468a596066 Mon Sep 17 00:00:00 2001 From: lbqds Date: Thu, 23 May 2024 11:11:50 +0800 Subject: [PATCH 3/7] Update tests --- test/exchange.test.ts | 74 ++++++------------------------------------- 1 file changed, 10 insertions(+), 64 deletions(-) diff --git a/test/exchange.test.ts b/test/exchange.test.ts index b4cf8840c..fae997e3e 100644 --- a/test/exchange.test.ts +++ b/test/exchange.test.ts @@ -24,13 +24,13 @@ import { ONE_ALPH, NodeProvider, prettifyAttoAlphAmount, - Subscription, node, sleep, TOTAL_NUMBER_OF_GROUPS, ALPH_TOKEN_ID, getALPHDepositInfo, - groupOfAddress + groupOfAddress, + BlockSubscription } from '@alephium/web3' import { waitTxConfirmed } from '@alephium/cli' import { EventEmitter } from 'stream' @@ -102,66 +102,6 @@ class User { } } -class BlockPoller extends Subscription { - readonly nodeProvider: NodeProvider - readonly fromGroup: number - readonly toGroup: number - private fromBlockHeight: number - - constructor( - nodeProvider: NodeProvider, - fromGroup: number, - toGroup: number, - callback: (block: node.BlockEntry) => Promise, - fromBlockHeight: number - ) { - super({ - pollingInterval: 1000, - messageCallback: callback, - errorCallback: (err) => { - console.error(err) - } - }) - this.nodeProvider = nodeProvider - this.fromGroup = fromGroup - this.toGroup = toGroup - this.fromBlockHeight = fromBlockHeight - } - - override startPolling(): void { - this.eventEmitter.on('tick', async () => { - await this.polling() - }) - this.eventEmitter.emit('tick') - } - - override async polling(): Promise { - try { - const chainInfo = await this.nodeProvider.blockflow.getBlockflowChainInfo({ - fromGroup: this.fromGroup, - toGroup: this.toGroup - }) - if (this.cancelled) { - return - } - - while (this.fromBlockHeight <= chainInfo.currentHeight) { - const result = await this.nodeProvider.blockflow.getBlockflowHashes({ - fromGroup: this.fromGroup, - toGroup: this.toGroup, - height: this.fromBlockHeight - }) - const block = await this.nodeProvider.blockflow.getBlockflowBlocksBlockHash(result.headers[0]) - await this.messageCallback(block) - this.fromBlockHeight += 1 - } - this.task = setTimeout(() => this.eventEmitter.emit('tick'), this.pollingInterval) - } catch (err) { - await this.errorCallback(err, this) - } - } -} - class Exchange { readonly nodeProvider: NodeProvider readonly wallet: PrivateKeyWallet @@ -229,8 +169,14 @@ class Exchange { fromGroup: fromGroup, toGroup: toGroup }) - const poller = new BlockPoller(this.nodeProvider, fromGroup, toGroup, callback, chainInfo.currentHeight + 1) - poller.startPolling() + const options = { + pollingInterval: 1000, + messageCallback: callback, + errorCallback: (err: any) => { + console.error(err) + } + } + new BlockSubscription(options, fromGroup, toGroup, chainInfo.currentHeight + 1) } } } From a74d0f333b8c1d51ad3b3b57e761f9dfb76d4742 Mon Sep 17 00:00:00 2001 From: lbqds Date: Thu, 23 May 2024 13:13:56 +0800 Subject: [PATCH 4/7] Rename --- packages/web3/src/utils/block.test.ts | 4 ++-- packages/web3/src/utils/block.ts | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/web3/src/utils/block.test.ts b/packages/web3/src/utils/block.test.ts index f2c61f66e..28440760a 100644 --- a/packages/web3/src/utils/block.test.ts +++ b/packages/web3/src/utils/block.test.ts @@ -126,7 +126,7 @@ describe('block subscription', function () { class BlockSubscriptionTest extends BlockSubscriptionBase { readonly fromGroup: number readonly toGroup: number - readonly onReorgCallback?: ReorgCallback + readonly reorgCallback?: ReorgCallback readonly hashesByHeight: Map readonly blockByHash: Map @@ -150,7 +150,7 @@ describe('block subscription', function () { super(options) this.fromGroup = fromGroup this.toGroup = toGroup - this.onReorgCallback = options.reorgCallback + this.reorgCallback = options.reorgCallback this.hashesByHeight = buildHashesByHeightMap(chains) this.blockByHash = buildBlockByHashMap(chains, fromGroup, toGroup) } diff --git a/packages/web3/src/utils/block.ts b/packages/web3/src/utils/block.ts index 4f2965b2b..df41b8f06 100644 --- a/packages/web3/src/utils/block.ts +++ b/packages/web3/src/utils/block.ts @@ -28,7 +28,7 @@ export interface BlockSubscribeOptions extends SubscribeOptions } export abstract class BlockSubscriptionBase extends Subscription { - abstract readonly onReorgCallback?: ReorgCallback + abstract readonly reorgCallback?: ReorgCallback abstract readonly fromGroup: number abstract readonly toGroup: number @@ -42,7 +42,7 @@ export abstract class BlockSubscriptionBase extends Subscription b.hash)}, new hashes: ${newBlocks.map((b) => b.hash)}`) - await this.onReorgCallback(orphanBlocks, newBlocks) + await this.reorgCallback(orphanBlocks, newBlocks) } } @@ -82,7 +82,7 @@ export class BlockSubscription extends BlockSubscriptionBase { readonly nodeProvider: NodeProvider readonly fromGroup: number readonly toGroup: number - readonly onReorgCallback?: ReorgCallback + readonly reorgCallback?: ReorgCallback private currentBlockHeight: number private parentBlockHash: string | undefined @@ -97,7 +97,7 @@ export class BlockSubscription extends BlockSubscriptionBase { this.nodeProvider = nodeProvider ?? web3.getCurrentNodeProvider() this.fromGroup = fromGroup this.toGroup = toGroup - this.onReorgCallback = options.reorgCallback + this.reorgCallback = options.reorgCallback this.currentBlockHeight = fromBlockHeight this.parentBlockHash = undefined From 65735f6672f8d7ed071fcb1af0d06722fb77af23 Mon Sep 17 00:00:00 2001 From: lbqds Date: Sat, 25 May 2024 07:18:42 +0800 Subject: [PATCH 5/7] Address comments --- packages/web3/src/contract/events.ts | 6 +++--- packages/web3/src/transaction/status.ts | 6 +++--- packages/web3/src/utils/block.test.ts | 2 +- packages/web3/src/utils/block.ts | 4 +--- packages/web3/src/utils/subscription.ts | 4 ++-- test/events.test.ts | 2 +- test/exchange.test.ts | 3 ++- 7 files changed, 13 insertions(+), 14 deletions(-) diff --git a/packages/web3/src/contract/events.ts b/packages/web3/src/contract/events.ts index c3879db74..9fe49ee71 100644 --- a/packages/web3/src/contract/events.ts +++ b/packages/web3/src/contract/events.ts @@ -34,8 +34,6 @@ export class EventSubscription extends Subscription { this.contractAddress = contractAddress this.fromCount = typeof fromCount === 'undefined' ? 0 : fromCount this.onEventCountChanged = options.onEventCountChanged - - this.startPolling() } currentEventCount(): number { @@ -71,5 +69,7 @@ export function subscribeToEvents( contractAddress: string, fromCount?: number ): EventSubscription { - return new EventSubscription(options, contractAddress, fromCount) + const subscription = new EventSubscription(options, contractAddress, fromCount) + subscription.subscribe() + return subscription } diff --git a/packages/web3/src/transaction/status.ts b/packages/web3/src/transaction/status.ts index b0e38ee72..612149ab4 100644 --- a/packages/web3/src/transaction/status.ts +++ b/packages/web3/src/transaction/status.ts @@ -40,8 +40,6 @@ export class TxStatusSubscription extends Subscription { this.fromGroup = fromGroup this.toGroup = toGroup this.confirmations = confirmations ?? 1 - - this.startPolling() } override async polling(): Promise { @@ -69,5 +67,7 @@ export function subscribeToTxStatus( toGroup?: number, confirmations?: number ): TxStatusSubscription { - return new TxStatusSubscription(options, txId, fromGroup, toGroup, confirmations) + const subscription = new TxStatusSubscription(options, txId, fromGroup, toGroup, confirmations) + subscription.subscribe() + return subscription } diff --git a/packages/web3/src/utils/block.test.ts b/packages/web3/src/utils/block.test.ts index 28440760a..6d8f9ef77 100644 --- a/packages/web3/src/utils/block.test.ts +++ b/packages/web3/src/utils/block.test.ts @@ -87,8 +87,8 @@ describe('block subscription', function () { if (!hashes.includes(c[currentHeight])) { hashes.push(c[currentHeight]) } - hashesByHeight.set(currentHeight, hashes) }) + hashesByHeight.set(currentHeight, hashes) } return hashesByHeight } diff --git a/packages/web3/src/utils/block.ts b/packages/web3/src/utils/block.ts index df41b8f06..25204a492 100644 --- a/packages/web3/src/utils/block.ts +++ b/packages/web3/src/utils/block.ts @@ -41,7 +41,7 @@ export abstract class BlockSubscriptionBase extends Subscription { diff --git a/packages/web3/src/utils/subscription.ts b/packages/web3/src/utils/subscription.ts index f9f585221..dac1a761f 100644 --- a/packages/web3/src/utils/subscription.ts +++ b/packages/web3/src/utils/subscription.ts @@ -45,7 +45,7 @@ export abstract class Subscription { this.eventEmitter = new EventEmitter() } - startPolling(): void { + subscribe(): void { this.eventEmitter.on('tick', async () => { await this.polling() @@ -68,5 +68,5 @@ export abstract class Subscription { return this.cancelled } - abstract polling(): Promise + protected abstract polling(): Promise } diff --git a/test/events.test.ts b/test/events.test.ts index 122451367..e67db445c 100644 --- a/test/events.test.ts +++ b/test/events.test.ts @@ -31,7 +31,7 @@ import { Main, DestroyAdd } from '../artifacts/ts/scripts' import { CreateContractEventAddresses, DestroyContractEventAddresses } from '../packages/web3' import { ContractCreatedEvent, subscribeContractCreatedEvent } from '../packages/web3' import { ContractDestroyedEvent, subscribeContractDestroyedEvent } from '../packages/web3' -import { PrivateKeyWallet } from '@alephium/web3-wallet/dist/src/privatekey-wallet' +import { PrivateKeyWallet } from '@alephium/web3-wallet' import { getSigner } from '@alephium/web3-test' describe('events', function () { diff --git a/test/exchange.test.ts b/test/exchange.test.ts index fae997e3e..be1ecf002 100644 --- a/test/exchange.test.ts +++ b/test/exchange.test.ts @@ -176,7 +176,8 @@ class Exchange { console.error(err) } } - new BlockSubscription(options, fromGroup, toGroup, chainInfo.currentHeight + 1) + const subscription = new BlockSubscription(options, fromGroup, toGroup, chainInfo.currentHeight + 1) + subscription.subscribe() } } } From af4abc8c1c8d8689a1530c9d8454a00db9cff3be Mon Sep 17 00:00:00 2001 From: lbqds Date: Sat, 25 May 2024 07:32:19 +0800 Subject: [PATCH 6/7] Move to src/block --- .../web3/src/{utils => block}/block.test.ts | 0 packages/web3/src/{utils => block}/block.ts | 2 +- packages/web3/src/block/index.ts | 19 +++++++++++++++++++ packages/web3/src/index.ts | 1 + packages/web3/src/utils/index.ts | 1 - 5 files changed, 21 insertions(+), 2 deletions(-) rename packages/web3/src/{utils => block}/block.test.ts (100%) rename packages/web3/src/{utils => block}/block.ts (98%) create mode 100644 packages/web3/src/block/index.ts diff --git a/packages/web3/src/utils/block.test.ts b/packages/web3/src/block/block.test.ts similarity index 100% rename from packages/web3/src/utils/block.test.ts rename to packages/web3/src/block/block.test.ts diff --git a/packages/web3/src/utils/block.ts b/packages/web3/src/block/block.ts similarity index 98% rename from packages/web3/src/utils/block.ts rename to packages/web3/src/block/block.ts index 25204a492..0113dd9ec 100644 --- a/packages/web3/src/utils/block.ts +++ b/packages/web3/src/block/block.ts @@ -16,7 +16,7 @@ You should have received a copy of the GNU Lesser General Public License along with the library. If not, see . */ -import { Subscription, SubscribeOptions } from './subscription' +import { Subscription, SubscribeOptions } from '../utils/subscription' import * as node from '../api/api-alephium' import { NodeProvider } from '../api' import * as web3 from '../global' diff --git a/packages/web3/src/block/index.ts b/packages/web3/src/block/index.ts new file mode 100644 index 000000000..ebcf44c1a --- /dev/null +++ b/packages/web3/src/block/index.ts @@ -0,0 +1,19 @@ +/* +Copyright 2018 - 2022 The Alephium Authors +This file is part of the alephium project. + +The library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the library. If not, see . +*/ + +export { ReorgCallback, BlockSubscribeOptions, BlockSubscription } from './block' diff --git a/packages/web3/src/index.ts b/packages/web3/src/index.ts index 0818884cb..d56f445fa 100644 --- a/packages/web3/src/index.ts +++ b/packages/web3/src/index.ts @@ -32,3 +32,4 @@ export * as web3 from './global' export * as codec from './codec' export * as utils from './utils' export * from './debug' +export * from './block' diff --git a/packages/web3/src/utils/index.ts b/packages/web3/src/utils/index.ts index 46a3356ec..d11ecba64 100644 --- a/packages/web3/src/utils/index.ts +++ b/packages/web3/src/utils/index.ts @@ -25,4 +25,3 @@ export * from './subscription' export * from './sign' export * from './number' export { validateExchangeAddress, isALPHTransferTx, getSenderAddress, getALPHDepositInfo } from './exchange' -export { ReorgCallback, BlockSubscribeOptions, BlockSubscription } from './block' From 16602bde5a320235418e923ac45d4b2ab5c20781 Mon Sep 17 00:00:00 2001 From: lbqds Date: Sat, 25 May 2024 07:48:40 +0800 Subject: [PATCH 7/7] Fix script codec tests --- packages/web3/src/codec/script-codec.test.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/web3/src/codec/script-codec.test.ts b/packages/web3/src/codec/script-codec.test.ts index 8a3a4d213..04d595efc 100644 --- a/packages/web3/src/codec/script-codec.test.ts +++ b/packages/web3/src/codec/script-codec.test.ts @@ -175,7 +175,9 @@ describe('Encode & decode scripts', function () { testScript(DestroyAdd.script, { add: contractId, caller: testAddress }, [ { isPublic: true, - assetModifier: 3, + usePreapprovedAssets: true, + useContractAssets: false, + usePayToContractOnly: false, argsLength: 0, localsLength: 0, returnLength: 0, @@ -186,7 +188,9 @@ describe('Encode & decode scripts', function () { testScript(GreeterMain.script, { greeterContractId: contractId }, [ { isPublic: true, - assetModifier: 3, + usePreapprovedAssets: true, + useContractAssets: false, + usePayToContractOnly: false, argsLength: 0, localsLength: 2, returnLength: 0, @@ -238,7 +242,9 @@ describe('Encode & decode scripts', function () { expect(decodedTxScript.methods.length).toEqual(methods.length) decodedTxScript.methods.map((decodedMethod, index) => { expect(decodedMethod.isPublic).toEqual(methods[index].isPublic) - expect(decodedMethod.assetModifier).toEqual(methods[index].assetModifier) + expect(decodedMethod.usePreapprovedAssets).toEqual(methods[index].usePreapprovedAssets) + expect(decodedMethod.useContractAssets).toEqual(methods[index].useContractAssets) + expect(decodedMethod.usePayToContractOnly).toEqual(methods[index].usePayToContractOnly) expect(decodedMethod.argsLength).toEqual(methods[index].argsLength) expect(decodedMethod.localsLength).toEqual(methods[index].localsLength) expect(decodedMethod.returnLength).toEqual(methods[index].returnLength)