Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Qi UTXO related types #204

Merged
merged 20 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
3 changes: 2 additions & 1 deletion src/contract/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import type { BytesLike } from '../utils/index.js';
import { getZoneForAddress, isQiAddress } from '../utils/index.js';
import type { ContractInterface, ContractMethodArgs, ContractDeployTransaction, ContractRunner } from './types.js';
import type { ContractTransactionResponse } from './wrappers.js';
import { Wallet, randomBytes } from '../quais.js';
import { Wallet } from '../wallet/index.js';
import { randomBytes } from '../crypto/index.js';
import { getContractAddress } from '../address/address.js';
import { getStatic } from '../utils/properties.js';
import { QuaiTransactionRequest } from '../providers/provider.js';
Expand Down
23 changes: 14 additions & 9 deletions src/providers/abstract-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// migrate the listener to the static event. We also need to maintain a map
// of Signer to address so we can sync respond to listenerCount.

import { getAddress, resolveAddress } from '../address/index.js';
import { computeAddress, resolveAddress } from '../address/index.js';
import { Shard, toShard, toZone, Zone } from '../constants/index.js';
import { TxInput, TxOutput } from '../transaction/index.js';
import { Outpoint } from '../transaction/utxo.js';
Expand Down Expand Up @@ -58,6 +58,7 @@ import type { Networkish } from './network.js';
import type {
BlockParams,
LogParams,
OutpointResponseParams,
QiTransactionResponseParams,
TransactionReceiptParams,
TransactionResponseParams,
Expand All @@ -76,7 +77,6 @@ import type {
import { WorkObjectLike } from '../transaction/work-object.js';
import { QiTransaction, QuaiTransaction } from '../transaction/index.js';
import { QuaiTransactionResponseParams } from './formatting.js';
import { keccak256, SigningKey } from '../crypto/index.js';

type Timer = ReturnType<typeof setTimeout>;

Expand Down Expand Up @@ -1098,12 +1098,8 @@ export class AbstractProvider<C = FetchRequest> implements Provider {

const addr = Array.isArray((<any>request)[key])
? 'address' in <any>request[key][0]
? (<TxOutput[]>(<any>request)[key]).map((it) => resolveAddress(hexlify(it.address)))
: (<TxInput[]>(<any>request)[key]).map((it) =>
getAddress(
keccak256('0x' + SigningKey.computePublicKey(it.pub_key).substring(4)).substring(26),
),
)
? (<TxOutput[]>(<any>request)[key]).map((it) => it.address)
: (<TxInput[]>(<any>request)[key]).map((it) => computeAddress(it.pubkey))
: resolveAddress((<any>request)[key]);
if (isPromise(addr)) {
if (Array.isArray(addr)) {
Expand Down Expand Up @@ -1320,7 +1316,16 @@ export class AbstractProvider<C = FetchRequest> implements Provider {
}

async getOutpointsByAddress(address: AddressLike): Promise<Outpoint[]> {
return await this.#getAccountValue({ method: 'getOutpointsByAddress' }, address, 'latest');
const outpoints: OutpointResponseParams[] = await this.#getAccountValue(
{ method: 'getOutpointsByAddress' },
address,
'latest',
);
return outpoints.map((outpoint: OutpointResponseParams) => ({
txhash: outpoint.Txhash,
index: outpoint.Index,
denomination: outpoint.Denomination,
}));
}

async getTransactionCount(address: AddressLike, blockTag?: BlockTag): Promise<number> {
Expand Down
23 changes: 21 additions & 2 deletions src/providers/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { getAddress } from '../address/index.js';
import { Signature } from '../crypto/index.js';
import { accessListify } from '../transaction/index.js';
import { hexlify } from '../utils/data';
import {
getBigInt,
getNumber,
Expand Down Expand Up @@ -380,8 +381,8 @@ export function formatTransactionResponse(value: any): TransactionResponseParams
index: allowNull((value: any) => (value ? BigInt(value) : null), null),
chainId: allowNull((value: any) => (value ? BigInt(value) : null), null),
signature: (value: any) => value,
txInputs: allowNull((value: any) => value, null),
txOutputs: allowNull((value: any) => value, null),
txInputs: allowNull((value: any) => value.map(_formatTxInput), null),
txOutputs: allowNull((value: any) => value.map(_formatTxOutput), null),
},
{
index: ['transactionIndex'],
Expand All @@ -396,3 +397,21 @@ export function formatTransactionResponse(value: any): TransactionResponseParams

return result;
}

const _formatTxInput = object(
{
txhash: formatHash,
index: getNumber,
pubkey: hexlify,
},
{
txhash: ['previous_out_point', 'hash', 'value'],
index: ['previous_out_point', 'index'],
pubkey: ['pub_key'],
},
);

const _formatTxOutput = object({
address: (addr: string) => hexlify(getAddress(addr)),
denomination: getNumber,
});
6 changes: 6 additions & 0 deletions src/providers/formatting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -435,3 +435,9 @@ export interface QiTransactionResponseParams {

txInputs?: TxInput[];
}

export interface OutpointResponseParams {
Txhash: string;
Index: number;
Denomination: number;
}
36 changes: 7 additions & 29 deletions src/providers/provider-jsonrpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// https://playground.open-rpc.org/?schemaUrl=https://raw.githubusercontent.com/ethereum/eth1.0-apis/assembled-spec/openrpc.json&uiSchema%5BappBar%5D%5Bui:splitView%5D=true&uiSchema%5BappBar%5D%5Bui:input%5D=false&uiSchema%5BappBar%5D%5Bui:examplesDropdown%5D=false

import { AbiCoder } from '../abi/index.js';
import { getAddress } from '../address/index.js';
import { getAddress, resolveAddress } from '../address/index.js';
import { accessListify, QuaiTransactionLike } from '../transaction/index.js';
import {
getBigInt,
Expand All @@ -26,30 +26,22 @@ import {
isError,
FetchRequest,
defineProperties,
getBytes,
resolveProperties,
} from '../utils/index.js';

import { AbstractProvider, UnmanagedSubscriber } from './abstract-provider.js';
import { Network } from './network.js';
import { FilterIdEventSubscriber, FilterIdPendingSubscriber } from './subscriber-filterid.js';

import type { TransactionLike } from '../transaction/index.js';
import type { TransactionLike, TxInput, TxOutput } from '../transaction/index.js';

import type { PerformActionRequest, Subscriber, Subscription } from './abstract-provider.js';
import type { Networkish } from './network.js';
import type { Provider, QuaiTransactionRequest, TransactionRequest, TransactionResponse } from './provider.js';
import { UTXOEntry, UTXOTransactionOutput } from '../transaction/utxo.js';
import { Shard, toShard } from '../constants/index.js';
import {
AbstractSigner,
resolveAddress,
Signer,
toUtf8Bytes,
TypedDataDomain,
TypedDataEncoder,
TypedDataField,
} from '../quais';
import { TypedDataDomain, TypedDataEncoder, TypedDataField } from '../hash/index.js';
import { AbstractSigner, Signer } from '../signers/index.js';
import { toUtf8Bytes } from '../encoding/index.js';
import { addressFromTransactionRequest } from './provider.js';

type Timer = ReturnType<typeof setTimeout>;
Expand Down Expand Up @@ -234,9 +226,9 @@ export interface AbstractJsonRpcTransactionRequest {
export type JsonRpcTransactionRequest = QiJsonRpcTransactionRequest | QuaiJsonRpcTransactionRequest;

export interface QiJsonRpcTransactionRequest extends AbstractJsonRpcTransactionRequest {
txInputs?: Array<UTXOEntry>;
txInputs?: Array<TxInput>;

txOutputs?: Array<UTXOTransactionOutput>;
txOutputs?: Array<TxOutput>;
}

/**
Expand Down Expand Up @@ -374,20 +366,6 @@ export class JsonRpcSigner extends AbstractSigner<JsonRpcApiProvider> {
})(),
);
}
} else {
// Make sure the from matches the sender
if (tx.outputs) {
for (let i = 0; i < tx.outputs.length; i++) {
if (tx.outputs[i].address) {
promises.push(
(async () => {
const address = await resolveAddress(hexlify(tx.outputs![i].address));
tx.outputs![i].address = getBytes(address);
})(),
);
}
}
}
}

// Wait until all of our properties are filled in
Expand Down
9 changes: 3 additions & 6 deletions src/providers/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ import {
isError,
makeError,
} from '../utils/index.js';
import { getAddress } from '../address/index.js';
import { computeAddress } from '../address/index.js';
import { accessListify } from '../transaction/index.js';
import { keccak256, SigningKey } from '../crypto/index.js';

import type { AddressLike } from '../address/index.js';
import type { BigNumberish, EventEmitterable } from '../utils/index.js';
Expand Down Expand Up @@ -135,9 +134,7 @@ export function addressFromTransactionRequest(tx: TransactionRequest): AddressLi
return tx.from;
}
if (tx.inputs) {
return getAddress(
keccak256('0x' + SigningKey.computePublicKey(tx.inputs[0].pub_key).substring(4)).substring(26),
);
return computeAddress(tx.inputs[0].pubkey);
}
if ('to' in tx && tx.to !== null) {
return tx.to as AddressLike;
Expand Down Expand Up @@ -2441,7 +2438,7 @@ export interface Provider extends ContractRunner, EventEmitterable<ProviderEvent
*
* @param {AddressLike} address - The address to fetch the UTXO entries for.
*
* @returns {Promise<UTXOEntry[]>} A promise resolving to the UTXO entries.
* @returns {Promise<Outpoint[]>} A promise resolving to the UTXO entries.
* @note On nodes without archive access enabled, the `blockTag` may be
* **silently ignored** by the node, which may cause issues if relied on.
*/
Expand Down
32 changes: 29 additions & 3 deletions src/transaction/abstract-transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { getBigInt, assert, assertArgument } from '../utils/index.js';
import type { BigNumberish } from '../utils/index.js';
import type { SignatureLike } from '../crypto/index.js';
import { encodeProtoTransaction } from '../encoding/proto-encode.js';
import type { TxInput, TxOutput } from './utxo.js';
import { Zone } from '../constants/index.js';

/**
Expand Down Expand Up @@ -147,19 +146,46 @@ export interface ProtoTransaction {
/**
* @todo Write documentation for this property.
*/
tx_ins?: { tx_ins: Array<TxInput> };
tx_ins?: { tx_ins: Array<ProtoTxInput> };

/**
* @todo Write documentation for this property.
*/
tx_outs?: { tx_outs: Array<TxOutput> };
tx_outs?: { tx_outs: Array<ProtoTxOutput> };

/**
* @todo Write documentation for this property.
*/
signature?: Uint8Array;
}

/**
* @category Transaction
* @todo Write documentation for this type.
*
* @todo If not used, replace with `ignore`
*/
export type ProtoTxOutput = {
address: Uint8Array;
denomination: number;
};

/**
* @category Transaction
* @todo Write documentation for this type.
*
* @todo If not used, replace with `ignore`
*/
export type ProtoTxInput = {
previous_out_point: {
hash: {
value: Uint8Array;
};
index: number;
};
pub_key: Uint8Array;
};

/**
* @category Transaction
* @todo Write documentation for this interface.
Expand Down
38 changes: 29 additions & 9 deletions src/transaction/qi-transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ export class QiTransaction extends AbstractTransaction<string> implements QiTran
throw new Error('Transaction must have at least one input and one output');
}

const pubKey = hexlify(this.txInputs[0].pub_key);
const senderAddr = computeAddress(pubKey || '');
const senderAddr = computeAddress(this.txInputs[0].pubkey || '');

if (!this.destZone || !this.originZone) {
throw new Error(
Expand Down Expand Up @@ -98,8 +97,7 @@ export class QiTransaction extends AbstractTransaction<string> implements QiTran
* The zone of the sender address
*/
get originZone(): Zone | undefined {
const pubKey = hexlify(this.txInputs[0].pub_key);
const senderAddr = computeAddress(pubKey || '');
const senderAddr = computeAddress(this.txInputs[0].pubkey || '');

const zone = getZoneForAddress(senderAddr);
return zone ?? undefined;
Expand All @@ -109,7 +107,7 @@ export class QiTransaction extends AbstractTransaction<string> implements QiTran
* The zone of the recipient address
*/
get destZone(): Zone | undefined {
const zone = getZoneForAddress(hexlify(this.txOutputs[0].address) || '');
const zone = getZoneForAddress(this.txOutputs[0].address);
return zone ?? undefined;
}

Expand Down Expand Up @@ -183,8 +181,21 @@ export class QiTransaction extends AbstractTransaction<string> implements QiTran
const protoTx: ProtoTransaction = {
type: this.type || 2,
chain_id: formatNumber(this.chainId || 0, 'chainId'),
tx_ins: { tx_ins: this.txInputs },
tx_outs: { tx_outs: this.txOutputs },
tx_ins: {
tx_ins: this.txInputs.map((input) => ({
previous_out_point: {
hash: { value: getBytes(input.txhash) },
index: input.index,
},
pub_key: getBytes(input.pubkey),
})),
},
tx_outs: {
tx_outs: this.txOutputs.map((output) => ({
address: getBytes(output.address),
denomination: output.denomination,
})),
},
};

if (this.signature && includeSignature) {
Expand Down Expand Up @@ -246,8 +257,17 @@ export class QiTransaction extends AbstractTransaction<string> implements QiTran
tx.chainId = toBigInt(protoTx.chain_id);

if (protoTx.type == 2) {
tx.txInputs = protoTx.tx_ins?.tx_ins ?? [];
tx.txOutputs = protoTx.tx_outs?.tx_outs ?? [];
tx.txInputs =
protoTx.tx_ins?.tx_ins.map((input) => ({
txhash: hexlify(input.previous_out_point.hash.value),
index: input.previous_out_point.index,
pubkey: hexlify(input.pub_key),
})) ?? [];
tx.txOutputs =
protoTx.tx_outs?.tx_outs.map((output) => ({
address: hexlify(output.address),
denomination: output.denomination,
})) ?? [];
}

if (protoTx.signature) {
Expand Down
Loading
Loading