Skip to content

Commit

Permalink
Apply automatic changes
Browse files Browse the repository at this point in the history
  • Loading branch information
rileystephens28 authored and alejoacosta74 committed Oct 16, 2024
1 parent 03861af commit 703a25b
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/providers/abstract-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ import {
PollingEventSubscriber,
PollingOrphanSubscriber,
PollingTransactionSubscriber,
QiPollingTransactionSubscriber,
} from './subscriber-polling.js';
import { getNodeLocationFromZone, getZoneFromNodeLocation } from '../utils/shards.js';
import { fromShard } from '../constants/shards.js';
Expand Down Expand Up @@ -1055,7 +1056,7 @@ export class AbstractProvider<C = FetchRequest> implements Provider {
// For QiTransaction, use fromProto() directly
return new QiTransactionResponse(tx, this);
} else {
throw new Error('Unknown transaction type');
throw new Error(`Unknown transaction type: ${tx.type}`);
}
} catch (error) {
console.error('Error in _wrapTransactionResponse:', error);
Expand Down Expand Up @@ -1889,6 +1890,8 @@ export class AbstractProvider<C = FetchRequest> implements Provider {
return new PollingEventSubscriber(this as AbstractProvider, sub.filter);
case 'transaction':
return new PollingTransactionSubscriber(this as AbstractProvider, sub.hash, sub.zone);
case 'qiTransaction':
return new QiPollingTransactionSubscriber(this as AbstractProvider, sub.hash, sub.zone);
case 'orphan':
return new PollingOrphanSubscriber(this as AbstractProvider, sub.filter, sub.zone);
}
Expand Down
99 changes: 99 additions & 0 deletions src/providers/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2412,6 +2412,105 @@ export class QiTransactionResponse implements QiTransactionLike, QiTransactionRe
return blockNumber - this.blockNumber + 1;
}

async wait(_confirms?: number, _timeout?: number): Promise<null | QiTransactionResponse> {
const confirms = _confirms == null ? 1 : _confirms;
const timeout = _timeout == null ? 0 : _timeout;

const startBlock = this.startBlock;
let stopScanning = startBlock === -1 ? true : false;

const zoneFromInput = async (txInputs: Array<TxInput> | undefined): Promise<Zone> => {
if (!txInputs || txInputs.length === 0) {
throw new Error('No transaction inputs provided');
}

const firstInput = txInputs[0];
if (!firstInput.pubkey) {
throw new Error('Public key not found in the first transaction input');
}
const address = computeAddress(firstInput.pubkey);
const zone = getZoneForAddress(address);
if (!zone) {
throw new Error(`Invalid zone for address: ${address}`);
}
return zone;
};

const zone = await zoneFromInput(this.txInputs);

const response = await this.provider.getTransaction(this.hash, zone);
if (response && response.isMined() && confirms === 0) {
return response as QiTransactionResponse;
}

if (response) {
if ((await response.confirmations()) >= confirms) {
return response as QiTransactionResponse;
}
} else {
// Allow null only when the confirms is 0
if (confirms === 0) {
return null;
}
}

const waiter = new Promise((resolve, reject) => {
const cancellers: Array<() => void> = [];
const cancel = () => {
cancellers.forEach((c) => c());
};

cancellers.push(() => {
stopScanning = true;
});

if (timeout > 0) {
const timer = setTimeout(() => {
cancel();
reject(makeError('wait for transaction timeout', 'TIMEOUT'));
}, timeout);
cancellers.push(() => {
clearTimeout(timer);
});
}

const txListener = async (response: QiTransactionResponse) => {
if ((await response.confirmations()) >= confirms) {
cancel();
resolve(response);
}
};

cancellers.push(() => {
this.provider.off('qiTransaction', txListener, zone, this.hash);
});
this.provider.on('qiTransaction', txListener, zone, this.hash);

if (startBlock >= 0) {
const blockListener = async () => {
const currentBlock = await this.provider.getBlockNumber(toShard(zone));
if (currentBlock - startBlock >= confirms) {
const response = await this.provider.getTransaction(this.hash, zone);
if (response && response.isMined()) {
cancel();
resolve(response);
}
}

if (!stopScanning) {
this.provider.once('block', blockListener, zone);
}
};
cancellers.push(() => {
this.provider.off('block', blockListener, zone);
});
this.provider.once('block', blockListener, zone);
}
});

return await (<Promise<QiTransactionResponse>>waiter);
}

/**
* Returns `true` if this transaction has been included.
*
Expand Down
23 changes: 23 additions & 0 deletions src/providers/subscriber-polling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ export function getPollingSubscriber(provider: AbstractProvider, event: Provider
return new PollingTransactionSubscriber(provider, event, zone);
}

if (event === 'qiTransaction') {
assert(hash != null, "hash is required for 'qiTransaction' event", 'MISSING_ARGUMENT');
return new QiPollingTransactionSubscriber(provider, hash, zone);
}

assert(false, 'unsupported polling event', 'UNSUPPORTED_OPERATION', {
operation: 'getPollingSubscriber',
info: { event },
Expand Down Expand Up @@ -321,6 +326,24 @@ export class PollingTransactionSubscriber extends OnBlockSubscriber {
}
}

export class QiPollingTransactionSubscriber extends OnBlockSubscriber {
#hash: string;
#zone: Zone;

constructor(provider: AbstractProvider, hash: string, zone: Zone) {
super(provider, zone);
this.#hash = hash;
this.#zone = zone;
}

async _poll(blockNumber: number, provider: AbstractProvider): Promise<void> {
const tx = await provider.getTransaction(this.#hash, this.#zone);
if (tx) {
provider.emit(this.#hash, this.#zone, tx);
}
}
}

/**
* A **PollingEventSubscriber** will poll for a given filter for its logs.
*
Expand Down

0 comments on commit 703a25b

Please sign in to comment.