From 10767475bdb5cde3a42631f631d426bae666e0ad Mon Sep 17 00:00:00 2001 From: janniks <6362150+janniks@users.noreply.github.com> Date: Thu, 7 Mar 2024 16:54:29 +0100 Subject: [PATCH] fix: update remaining packages for api (#1625) Co-authored-by: janniks --- package-lock.json | 7 + packages/api/package.json | 1 + packages/api/src/api.ts | 137 +++++++-- packages/api/src/index.ts | 1 + packages/api/src/types.ts | 91 ++++++ packages/common/src/utils.ts | 4 +- packages/encryption/package.json | 1 + .../encryption/tests/messageSignature.test.ts | 3 +- packages/stacking/package.json | 1 + packages/stacking/src/index.ts | 290 ++++++------------ packages/stacking/tests/stacking.test.ts | 1 - packages/stacking/tsconfig.build.json | 7 +- packages/transactions/src/types.ts | 27 +- packages/transactions/src/utils.ts | 4 +- 14 files changed, 331 insertions(+), 244 deletions(-) create mode 100644 packages/api/src/types.ts diff --git a/package-lock.json b/package-lock.json index 677fd1926..100bee3da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23617,12 +23617,18 @@ "dependencies": { "@stacks/common": "^6.10.0", "@stacks/network": "^6.11.3", + "@stacks/stacks-blockchain-api-types": "^0.61.0", "@stacks/transactions": "^6.9.0" }, "devDependencies": { "rimraf": "^3.0.2" } }, + "packages/api/node_modules/@stacks/stacks-blockchain-api-types": { + "version": "0.61.0", + "resolved": "https://registry.npmjs.org/@stacks/stacks-blockchain-api-types/-/stacks-blockchain-api-types-0.61.0.tgz", + "integrity": "sha512-yPOfTUboo5eA9BZL/hqMcM71GstrFs9YWzOrJFPeP4cOO1wgYvAcckgBRbgiE3NqeX0A7SLZLDAXLZbATuRq9w==" + }, "packages/api/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -23818,6 +23824,7 @@ }, "devDependencies": { "@peculiar/webcrypto": "^1.1.6", + "@stacks/network": "^6.11.3", "@stacks/transactions": "^6.11.3", "@types/bs58check": "^2.1.0", "@types/elliptic": "^6.4.12", diff --git a/packages/api/package.json b/packages/api/package.json index fc09a7106..792323743 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -25,6 +25,7 @@ "dependencies": { "@stacks/common": "^6.10.0", "@stacks/network": "^6.11.3", + "@stacks/stacks-blockchain-api-types": "^0.61.0", "@stacks/transactions": "^6.9.0" }, "devDependencies": { diff --git a/packages/api/src/api.ts b/packages/api/src/api.ts index c2efdeea2..3174438f1 100644 --- a/packages/api/src/api.ts +++ b/packages/api/src/api.ts @@ -8,6 +8,12 @@ import { networkFrom, } from '@stacks/network'; import { + BurnchainRewardListResponse, + BurnchainRewardSlotHolderListResponse, + BurnchainRewardsTotal, +} from '@stacks/stacks-blockchain-api-types'; +import { + Cl, ClarityAbi, FeeEstimation, StacksTransaction, @@ -17,6 +23,14 @@ import { getAbi, getNonce, } from '@stacks/transactions'; +import { + BaseErrorResponse, + ExtendedAccountBalances, + PaginationOptions, + V1InfoBlockTimesResponse, + V2CoreInfoResponse as V2InfoResponse, + V2PoxInfoResponse, +} from './types'; export class StacksNodeApi { // TODO @@ -87,39 +101,106 @@ export class StacksNodeApi { /** * Fetch a contract's ABI - * @param contractAddress - The contracts address - * @param contractName - The contracts name * @returns A promise that resolves to a ClarityAbi if the operation succeeds */ - getAbi = async (contractAddress: string, contractName: string): Promise => { + getAbi = async (contract: `${string}.${string}`): Promise => { + const [contractAddress, contractName] = contract.split('.'); return getAbi({ contractAddress, contractName, api: this }); }; - // todo: migrate to new api pattern - getNameInfo(fullyQualifiedName: string) { - /* - TODO: Update to v2 API URL for name lookups - */ - const nameLookupURL = `${this.bnsLookupUrl}/v1/names/${fullyQualifiedName}`; - return this.fetch(nameLookupURL) - .then((resp: any) => { - if (resp.status === 404) { - throw new Error('Name not found'); - } else if (resp.status !== 200) { - throw new Error(`Bad response status: ${resp.status}`); - } else { - return resp.json(); - } - }) - .then((nameInfo: any) => { - // the returned address _should_ be in the correct network --- - // stacks node gets into trouble because it tries to coerce back to mainnet - // and the regtest transaction generation libraries want to use testnet addresses - if (nameInfo.address) { - return Object.assign({}, nameInfo, { address: nameInfo.address }); - } else { - return nameInfo; - } + /** Get stacks node info */ + getInfo(): Promise { + return this.fetch(`${this.url}/v2/info`).then(res => res.json()); + } + + /** Get stacks node pox info */ + getPoxInfo(): Promise { + return this.fetch(`${this.url}/v2/pox`).then(res => res.json()); + } + + /** Get stacks node target block time */ + async getTargetBlockTime() { + const res = await this.fetch(`${this.url}/extended/v1/info/network_block_times`).then( + (res: any): V1InfoBlockTimesResponse => res.json() + ); + + if (this.isMainnet()) return res.mainnet.target_block_time; + return res.testnet.target_block_time; + } + + /** Get account status */ + async getAccountInfo(address: string) { + // todo: add types for response + return this.fetch(`${this.url}/v2/accounts/${address}?proof=0`) + .then(res => res.json()) + .then(json => { + json.balance = BigInt(json.balance); + json.locked = BigInt(json.locked); + return json; + }); + } + + /** Get extended account balances */ + async getExtendedAccountBalances(address: string): Promise { + return this.fetch(`${this.url}/extended/v1/address/${address}/balances`) + .then(res => res.json()) + .then(json => { + json.stx.balance = BigInt(json.stx.balance); + json.stx.total_sent = BigInt(json.stx.total_sent); + json.stx.total_received = BigInt(json.stx.total_received); + json.stx.locked = BigInt(json.stx.locked); + return json; }); } + + /** Get the total BTC stacking rewards total for an address */ + async getExtendedBtcRewardsTotal( + /** BTC or STX address */ + address: string + ): Promise { + return this.fetch(`${this.url}/extended/v1/burnchain/rewards/${address}/total`) + .then(res => res.json()) + .then(json => { + json.reward_amount = BigInt(json.reward_amount); + return json; + }); + } + + /** Get paginated BTC stacking rewards total for an address */ + async getExtendedBtcRewards( + /** BTC or STX address */ + address: string, + options?: PaginationOptions + ): Promise { + let url = `${this.url}/extended/v1/burnchain/rewards/${address}`; + if (options) url += `?limit=${options.limit}&offset=${options.offset}`; + + return this.fetch(url).then(res => res.json()); + } + + /** Get BTC reward holders for the an address */ + async getExtendedBtcRewardHolders( + /** BTC or STX address */ + address: string, + options?: PaginationOptions + ): Promise { + let url = `${this.url}/extended/v1/burnchain/reward_slot_holders/${address}`; + if (options) url += `?limit=${options.limit}&offset=${options.offset}`; + + return this.fetch(url).then(res => res.json()); + } + + /** Gets the value of a data-var if it exists in the given contract */ + async getDataVar(contract: `${string}.${string}`, dataVarName: string) { + // todo: (contractAddress: string, contractName: string, dataVarName: string) overload? + // todo: cleanup address/contract identifies types + const contractPath = contract.replace('.', '/'); + const url = `${this.url}/v2/data_var/${contractPath}/${dataVarName}?proof=0`; + return this.fetch(url) + .then(res => res.json()) + .then(json => ({ + value: Cl.deserialize(json.value), + raw: json.data as string, + })); + } } diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index b1c13e734..4d4b4e299 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -1 +1,2 @@ export * from './api'; +export * from './types'; diff --git a/packages/api/src/types.ts b/packages/api/src/types.ts new file mode 100644 index 000000000..4fedb6ac5 --- /dev/null +++ b/packages/api/src/types.ts @@ -0,0 +1,91 @@ +export interface V2CoreInfoResponse { + burn_block_height: number; + stable_pox_consensus: string; +} + +export interface CycleInfoResponse { + id: number; + min_threshold_ustx: number; + stacked_ustx: number; + is_pox_active: boolean; +} + +export interface ContractVersionResponse { + contract_id: `${string}.${string}`; + activation_burnchain_block_height: number; + first_reward_cycle_id: number; +} + +export interface V2PoxInfoResponse { + contract_id: string; + contract_versions?: ContractVersionResponse[]; + current_burnchain_block_height?: number; + first_burnchain_block_height: number; + min_amount_ustx: string; + next_reward_cycle_in: number; + prepare_cycle_length: number; + prepare_phase_block_length: number; + rejection_fraction: number; + rejection_votes_left_required: number; + reward_cycle_id: number; + reward_cycle_length: number; + reward_phase_block_length: number; + reward_slots: number; + current_cycle: CycleInfoResponse; + next_cycle: CycleInfoResponse & { + min_increment_ustx: number; + prepare_phase_start_block_height: number; + blocks_until_prepare_phase: number; + reward_phase_start_block_height: number; + blocks_until_reward_phase: number; + ustx_until_pox_rejection: number; + }; +} + +export interface V1InfoBlockTimesResponse { + mainnet: { + target_block_time: number; + }; + testnet: { + target_block_time: number; + }; +} + +export interface ExtendedAccountBalancesResponse { + stx: { + balance: string; + total_sent: string; + total_received: string; + locked: string; + lock_tx_id: string; + lock_height: number; + burnchain_lock_height: number; + burnchain_unlock_height: number; + }; + fungible_tokens: any; + non_fungible_tokens: any; +} + +export interface ExtendedAccountBalances { + stx: { + balance: bigint; + total_sent: bigint; + total_received: bigint; + locked: bigint; + lock_tx_id: string; + lock_height: number; + burnchain_lock_height: number; + burnchain_unlock_height: number; + }; + fungible_tokens: any; + non_fungible_tokens: any; +} + +export interface PaginationOptions { + limit: number; + offset: number; +} + +export interface BaseErrorResponse { + error: string; +} diff --git a/packages/common/src/utils.ts b/packages/common/src/utils.ts index e1a71c87c..cfde85c78 100644 --- a/packages/common/src/utils.ts +++ b/packages/common/src/utils.ts @@ -629,8 +629,8 @@ export function concatArray(elements: (Uint8Array | number[] | number)[]) { * Better `instanceof` check for types in different environments * @ignore */ -export function isInstance(object: any, type: any) { - return object instanceof type || object?.constructor?.name?.toLowerCase() === type.name; +export function isInstance(object: any, clazz: { new (...args: any[]): T }): object is T { + return object instanceof clazz || object?.constructor?.name?.toLowerCase() === clazz.name; } /** diff --git a/packages/encryption/package.json b/packages/encryption/package.json index a3ba4bc68..3279f2c27 100644 --- a/packages/encryption/package.json +++ b/packages/encryption/package.json @@ -32,6 +32,7 @@ }, "devDependencies": { "@peculiar/webcrypto": "^1.1.6", + "@stacks/network": "^6.11.3", "@stacks/transactions": "^6.11.3", "@types/bs58check": "^2.1.0", "@types/elliptic": "^6.4.12", diff --git a/packages/encryption/tests/messageSignature.test.ts b/packages/encryption/tests/messageSignature.test.ts index 0a4773f7e..723386fa7 100644 --- a/packages/encryption/tests/messageSignature.test.ts +++ b/packages/encryption/tests/messageSignature.test.ts @@ -1,5 +1,6 @@ import { bytesToHex, concatBytes, equals, utf8ToBytes } from '@stacks/common'; -import { getAddressFromPublicKey, TransactionVersion } from '@stacks/transactions'; +import { TransactionVersion } from '@stacks/network'; +import { getAddressFromPublicKey } from '@stacks/transactions'; import { verifyMessageSignatureRsv } from '../src/ec'; import { decodeMessage, encodeMessage, hashMessage } from '../src/messageSignature'; diff --git a/packages/stacking/package.json b/packages/stacking/package.json index b712d7c9a..246ffd2e8 100644 --- a/packages/stacking/package.json +++ b/packages/stacking/package.json @@ -21,6 +21,7 @@ }, "dependencies": { "@scure/base": "1.1.1", + "@stacks/api": "^6.11.3", "@stacks/common": "^6.10.0", "@stacks/encryption": "^6.11.3", "@stacks/network": "^6.11.3", diff --git a/packages/stacking/src/index.ts b/packages/stacking/src/index.ts index 5bef6a0fd..2ca06e324 100644 --- a/packages/stacking/src/index.ts +++ b/packages/stacking/src/index.ts @@ -1,5 +1,5 @@ // @ts-ignore -import { IntegerType, intToBigInt } from '@stacks/common'; +import { ApiOpts, IntegerType, intToBigInt, isInstance } from '@stacks/common'; import { StacksNetwork } from '@stacks/network'; import { BurnchainRewardListResponse, @@ -40,6 +40,13 @@ import { unwrap, unwrapMap, } from './utils'; +import { + BaseErrorResponse, + ContractVersionResponse, + PaginationOptions, + StacksNodeApi, + V2PoxInfoResponse, +} from '@stacks/api'; export * from './utils'; @@ -53,45 +60,6 @@ interface BaseTxOptions { privateKey: string; } -export interface CycleInfo { - id: number; - min_threshold_ustx: number; - stacked_ustx: number; - is_pox_active: boolean; -} - -export interface ContractVersion { - contract_id: string; - activation_burnchain_block_height: number; - first_reward_cycle_id: number; -} - -export interface PoxInfo { - contract_id: string; - contract_versions?: ContractVersion[]; - current_burnchain_block_height?: number; - first_burnchain_block_height: number; - min_amount_ustx: string; - next_reward_cycle_in: number; - prepare_cycle_length: number; - prepare_phase_block_length: number; - rejection_fraction: number; - rejection_votes_left_required: number; - reward_cycle_id: number; - reward_cycle_length: number; - reward_phase_block_length: number; - reward_slots: number; - current_cycle: CycleInfo; - next_cycle: CycleInfo & { - min_increment_ustx: number; - prepare_phase_start_block_height: number; - blocks_until_prepare_phase: number; - reward_phase_start_block_height: number; - blocks_until_reward_phase: number; - ustx_until_pox_rejection: number; - }; -} - export type PoxOperationInfo = | { period: PoxOperationPeriod.Period1; @@ -100,32 +68,17 @@ export type PoxOperationInfo = | { period: PoxOperationPeriod; pox1: { contract_id: string }; - pox2: ContractVersion; - current: ContractVersion; + pox2: ContractVersionResponse; + current: ContractVersionResponse; } | { period: PoxOperationPeriod.Period3; pox1: { contract_id: string }; - pox2: ContractVersion; - pox3: ContractVersion; - current: ContractVersion; + pox2: ContractVersionResponse; + pox3: ContractVersionResponse; + current: ContractVersionResponse; }; -export interface AccountExtendedBalances { - stx: { - balance: IntegerType; - total_sent: IntegerType; - total_received: IntegerType; - locked: IntegerType; - lock_tx_id: string; - lock_height: number; - burnchain_lock_height: number; - burnchain_unlock_height: number; - }; - fungible_tokens: any; - non_fungible_tokens: any; -} - export type StackerInfo = | { stacked: false; @@ -160,34 +113,6 @@ export type DelegationInfo = }; }; -export interface BlockTimeInfo { - mainnet: { - target_block_time: number; - }; - testnet: { - target_block_time: number; - }; -} - -export interface CoreInfo { - burn_block_height: number; - stable_pox_consensus: string; -} - -export interface BalanceInfo { - balance: string; - nonce: number; -} - -export interface PaginationOptions { - limit: number; - offset: number; -} - -export interface RewardsError { - error: string; -} - export interface RewardSetOptions { contractId: string; rewardCyleId: number; @@ -333,83 +258,55 @@ export interface StackAggregationIncreaseOptions { } export class StackingClient { - constructor( - public address: string, - public network: StacksNetwork - ) {} + public address: string; + public network: StacksNetwork; - /** - * Get stacks node info - * - * @returns {Promise} that resolves to a CoreInfo response if the operation succeeds - */ - async getCoreInfo(): Promise { - const url = this.network.getInfoUrl(); - return this.network.fetchFn(url).then(res => res.json()); + public api: StacksNodeApi; + + constructor(opts: { address: string; network: StacksNetwork; api: StacksNodeApi | ApiOpts }) { + this.address = opts.address; + this.network = opts.network; + this.api = isInstance(opts.api, StacksNodeApi) + ? opts.api + : new StacksNodeApi({ url: opts.api.url, fetch: opts.api.fetch, network: opts.network }); } - /** - * Get stacks node pox info - * - * @returns {Promise} that resolves to a PoxInfo response if the operation succeeds - */ - async getPoxInfo(): Promise { - const url = this.network.getPoxInfoUrl(); - return this.network.fetchFn(url).then(res => res.json()); + /** @deprecated alias of StacksNodeApi.getCoreInfo, kept for backwards compatibility */ + getCoreInfo() { + return this.api.getInfo(); } - /** - * Get stacks node target block time - * - * @returns {Promise} resolves to a number if the operation succeeds - */ - async getTargetBlockTime(): Promise { - const url = this.network.getBlockTimeInfoUrl(); - const res = await this.network.fetchFn(url).then(res => res.json()); - - if (this.network.isMainnet()) { - return res.mainnet.target_block_time; - } else { - return res.testnet.target_block_time; - } + /** @deprecated alias of StacksNodeApi.getPoxInfo, kept for backwards compatibility */ + getPoxInfo() { + return this.api.getPoxInfo(); } + /** @deprecated alias of StacksNodeApi.getTargetBlockTime, kept for backwards compatibility */ + getTargetBlockTime() { + return this.api.getTargetBlockTime(); + } + + /** Get account status */ async getAccountStatus(): Promise { - const url = this.network.getAccountApiUrl(this.address); - return this.network.fetchFn(url).then(res => res.json()); + return this.api.getAccountInfo(this.address); } - /** - * Get account balance - * @returns {Promise} resolves to a bigint if the operation succeeds - */ + /** Get account balance */ async getAccountBalance(): Promise { - return this.getAccountStatus().then(res => { - return BigInt(res.balance); - }); + return this.api.getAccountInfo(this.address).then(a => a.balance); } - /** - * Get extended account balances - * @returns {Promise} resolves to an AccountExtendedBalances response if the operation succeeds - */ - async getAccountExtendedBalances(): Promise { - const url = this.network.getAccountExtendedBalancesApiUrl(this.address); - return this.network.fetchFn(url).then(res => res.json()); + /** Get extended account balances */ + async getAccountExtendedBalances() { + return this.api.getExtendedAccountBalances(this.address); } - /** - * Get account balance of locked tokens - * @returns {Promise} resolves to a bigint if the operation succeeds - */ + /** Get account balance of locked tokens */ async getAccountBalanceLocked(): Promise { - return this.getAccountStatus().then(res => BigInt(res.locked)); + return this.api.getAccountInfo(this.address).then(a => a.locked); } - /** - * Get reward cycle duration in seconds - * @returns {Promise} resolves to a number if the operation succeeds - */ + /** Get reward cycle duration in seconds */ async getCycleDuration(): Promise { const poxInfoPromise = this.getPoxInfo(); const targetBlockTimePromise = await this.getTargetBlockTime(); @@ -421,45 +318,30 @@ export class StackingClient { ); } - /** - * Get the total burnchain rewards total for the set address - * @returns {Promise} that resolves to TotalRewardsResponse or RewardsError - */ - async getRewardsTotalForBtcAddress(): Promise { - const url = this.network.getRewardsTotalUrl(this.address); - return this.network.fetchFn(url).then(res => res.json()); + /** Get the total burnchain rewards total for the set address */ + async getRewardsTotalForBtcAddress(): Promise { + return this.api.getExtendedBtcRewardsTotal(this.address); } - /** - * Get burnchain rewards for the set address - * @returns {Promise} that resolves to RewardsResponse or RewardsError - */ + /** Get burnchain rewards for the set address */ async getRewardsForBtcAddress( options?: PaginationOptions - ): Promise { - const url = `${this.network.getRewardsUrl(this.address, options)}`; - return this.network.fetchFn(url).then(res => res.json()); + ): Promise { + return this.api.getExtendedBtcRewards(this.address, options); } - /** - * Get burnchain rewards holders for the set address - * @returns {Promise} that resolves to RewardHoldersResponse or RewardsError - */ + /** Get burnchain rewards holders for the set address */ async getRewardHoldersForBtcAddress( options?: PaginationOptions - ): Promise { - const url = `${this.network.getRewardHoldersUrl(this.address, options)}`; - return this.network.fetchFn(url).then(res => res.json()); + ): Promise { + return this.api.getExtendedBtcRewardHolders(this.address, options); } - /** - * Get PoX address from reward set by index - * @returns {Promise} that resolves to RewardSetInfo if the entry exists - */ + /** Get PoX address from reward set by index (if it exists) */ async getRewardSet(options: RewardSetOptions): Promise { const [contractAddress, contractName] = this.parseContractId(options?.contractId); const result = await callReadOnlyFunction({ - network: this.network, + api: this.api, senderAddress: this.address, contractAddress, contractName, @@ -478,10 +360,7 @@ export class StackingClient { /** * Get number of seconds until next reward cycle - * @returns {Promise} resolves to a number if the operation succeeds - * - * See also: - * - {@link getSecondsUntilStackingDeadline} + * @see {@link getSecondsUntilStackingDeadline} */ async getSecondsUntilNextCycle(): Promise { const poxInfoPromise = this.getPoxInfo(); @@ -503,11 +382,9 @@ export class StackingClient { * Get number of seconds until the end of the stacking deadline. * This is the estimated time stackers have to submit their stacking * transactions to be included in the upcoming reward cycle. - * @returns {Promise} resolves to a number of seconds if the operation succeeds. + * @returns number of seconds * **⚠️ Attention**: The returned number of seconds can be negative if the deadline has passed and the prepare phase has started. - * - * See also: - * - {@link getSecondsUntilNextCycle} + * @see {@link getSecondsUntilNextCycle} */ async getSecondsUntilStackingDeadline(): Promise { const poxInfoPromise = this.getPoxInfo(); @@ -526,10 +403,8 @@ export class StackingClient { * - Period 1: This is before the 2.1 fork. * - Period 2: This is after the 2.1 fork, but before cycle (N+1). * - Period 3: This is after cycle (N+1) has begun. Original PoX contract state will no longer have any impact on reward sets, account lock status, etc. - * - * @returns {Promise} that resolves to PoX operation info */ - async getPoxOperationInfo(poxInfo?: PoxInfo): Promise { + async getPoxOperationInfo(poxInfo?: V2PoxInfoResponse): Promise { poxInfo = poxInfo ?? (await this.getPoxInfo()); // ++ Before 2.1 Fork ++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -548,17 +423,15 @@ export class StackingClient { ); // by activation height ASC (earliest first) const [pox1, pox2, pox3] = poxContractVersions; const activatedPoxs = poxContractVersions.filter( - (c: ContractVersion) => + (c: ContractVersionResponse) => (poxInfo?.current_burnchain_block_height as number) >= c.activation_burnchain_block_height ); // Named pox contracts but also a more future-proof current pointer to latest activated PoX contract const current = activatedPoxs[activatedPoxs.length - 1]; if (poxInfo.contract_versions.length == 2) { - const [address, name] = pox2.contract_id.split('.'); - const pox2ConfiguredUrl = this.network.getDataVarUrl(address, name, 'configured'); - const isPox2NotYetConfigured = - (await this.network.fetchFn(pox2ConfiguredUrl).then(r => r.text())) !== '{"data":"0x03"}'; // PoX-2 is configured on fork if data is 0x03 + const pox2ConfiguredDataVar = await this.api.getDataVar(pox2.contract_id, 'configured'); + const isPox2NotYetConfigured = pox2ConfiguredDataVar.raw !== '0x03'; // PoX-2 is configured on fork if data is 0x03 // => Period 1 if (isPox2NotYetConfigured) { @@ -630,7 +503,7 @@ export class StackingClient { const [contractAddress, contractName] = this.parseContractId(poxInfo.contract_id); return callReadOnlyFunction({ - network: this.network, + api: this.api, contractName, contractAddress, functionName: 'can-stack-stx', @@ -688,7 +561,7 @@ export class StackingClient { ...renamePrivateKey(txOptions), }); - return broadcastTransaction(tx, callOptions.network as StacksNetwork); + return broadcastTransaction({ transaction: tx, api: this.api }); } /** @@ -716,7 +589,7 @@ export class StackingClient { ...renamePrivateKey(txOptions), }); - return broadcastTransaction(tx, callOptions.network as StacksNetwork); + return broadcastTransaction({ transaction: tx, api: this.api }); } /** @@ -742,7 +615,7 @@ export class StackingClient { ...renamePrivateKey(txOptions), }); - return broadcastTransaction(tx, callOptions.network as StacksNetwork); + return broadcastTransaction({ transaction: tx, api: this.api }); } /** @@ -777,7 +650,7 @@ export class StackingClient { ...renamePrivateKey(txOptions), }); - return broadcastTransaction(tx, callOptions.network as StacksNetwork); + return broadcastTransaction({ transaction: tx, api: this.api }); } /** @@ -812,7 +685,7 @@ export class StackingClient { ...renamePrivateKey(txOptions), }); - return broadcastTransaction(tx, callOptions.network as StacksNetwork); + return broadcastTransaction({ transaction: tx, api: this.api }); } /** @@ -841,7 +714,7 @@ export class StackingClient { ...renamePrivateKey(txOptions), }); - return broadcastTransaction(tx, callOptions.network as StacksNetwork); + return broadcastTransaction({ transaction: tx, api: this.api }); } /** @@ -871,7 +744,7 @@ export class StackingClient { ...renamePrivateKey(txOptions), }); - return broadcastTransaction(tx, callOptions.network as StacksNetwork); + return broadcastTransaction({ transaction: tx, api: this.api }); } /** @@ -898,7 +771,7 @@ export class StackingClient { ...renamePrivateKey(txOptions), }); - return broadcastTransaction(tx, callOptions.network as StacksNetwork); + return broadcastTransaction({ transaction: tx, api: this.api }); } /** @@ -937,7 +810,7 @@ export class StackingClient { ...renamePrivateKey(txOptions), }); - return broadcastTransaction(tx, callOptions.network as StacksNetwork); + return broadcastTransaction({ transaction: tx, api: this.api }); } /** @@ -967,7 +840,7 @@ export class StackingClient { ...renamePrivateKey(txOptions), }); - return broadcastTransaction(tx, callOptions.network as StacksNetwork); + return broadcastTransaction({ transaction: tx, api: this.api }); } /** @@ -995,7 +868,7 @@ export class StackingClient { ...renamePrivateKey(arg), }); - return broadcastTransaction(tx, callOptions.network as StacksNetwork); + return broadcastTransaction({ transaction: tx, api: this.api }); } getStackOptions({ @@ -1014,6 +887,7 @@ export class StackingClient { const address = poxAddressToTuple(poxAddress); const [contractAddress, contractName] = this.parseContractId(contract); const callOptions: ContractCallOptions = { + api: this.api, contractAddress, contractName, functionName: 'stack-stx', @@ -1038,6 +912,7 @@ export class StackingClient { const address = poxAddressToTuple(poxAddress); const [contractAddress, contractName] = this.parseContractId(contract); const callOptions: ContractCallOptions = { + api: this.api, contractAddress, contractName, functionName: 'stack-extend', @@ -1052,6 +927,7 @@ export class StackingClient { getStackIncreaseOptions({ increaseBy, contract }: { increaseBy: IntegerType; contract: string }) { const [contractAddress, contractName] = this.parseContractId(contract); const callOptions: ContractCallOptions = { + api: this.api, contractAddress, contractName, functionName: 'stack-increase', @@ -1079,6 +955,7 @@ export class StackingClient { const address = poxAddress ? someCV(poxAddressToTuple(poxAddress)) : noneCV(); const [contractAddress, contractName] = this.parseContractId(contract); const callOptions: ContractCallOptions = { + api: this.api, contractAddress, contractName, functionName: 'delegate-stx', @@ -1113,6 +990,7 @@ export class StackingClient { const address = poxAddressToTuple(poxAddress); const [contractAddress, contractName] = this.parseContractId(contract); const callOptions: ContractCallOptions = { + api: this.api, contractAddress, contractName, functionName: 'delegate-stack-stx', @@ -1145,6 +1023,7 @@ export class StackingClient { const address = poxAddressToTuple(poxAddress); const [contractAddress, contractName] = this.parseContractId(contract); const callOptions: ContractCallOptions = { + api: this.api, contractAddress, contractName, functionName: 'delegate-stack-extend', @@ -1171,6 +1050,7 @@ export class StackingClient { const address = poxAddressToTuple(poxAddress); const [contractAddress, contractName] = this.parseContractId(contract); const callOptions: ContractCallOptions = { + api: this.api, contractAddress, contractName, functionName: 'delegate-stack-increase', @@ -1195,6 +1075,7 @@ export class StackingClient { const address = poxAddressToTuple(poxAddress); const [contractAddress, contractName] = this.parseContractId(contract); const callOptions: ContractCallOptions = { + api: this.api, contractAddress, contractName, functionName: 'stack-aggregation-commit', @@ -1220,6 +1101,7 @@ export class StackingClient { const address = poxAddressToTuple(poxAddress); const [contractAddress, contractName] = this.parseContractId(contract); const callOptions: ContractCallOptions = { + api: this.api, contractAddress, contractName, functionName: 'stack-aggregation-increase', @@ -1243,6 +1125,7 @@ export class StackingClient { const address = poxAddressToTuple(poxAddress); const [contractAddress, contractName] = this.parseContractId(contract); const callOptions: ContractCallOptions = { + api: this.api, contractAddress, contractName, functionName: 'stack-aggregation-commit-indexed', @@ -1257,6 +1140,7 @@ export class StackingClient { getRevokeDelegateStxOptions(contract: string) { const [contractAddress, contractName] = this.parseContractId(contract); const callOptions: ContractCallOptions = { + api: this.api, contractAddress, contractName, functionName: 'revoke-delegate-stx', @@ -1285,7 +1169,7 @@ export class StackingClient { functionName, senderAddress: this.address, functionArgs: [principalCV(this.address)], - network: this.network, + api: this.api, }).then((responseCV: ClarityValue) => { if (responseCV.type === ClarityType.OptionalSome) { const someCV = responseCV; @@ -1334,7 +1218,7 @@ export class StackingClient { functionName, senderAddress: this.address, functionArgs: [principalCV(this.address)], - network: this.network, + api: this.api, }).then((responseCV: ClarityValue) => { if (responseCV.type === ClarityType.OptionalSome) { const tupleCV = responseCV.value as TupleCV; diff --git a/packages/stacking/tests/stacking.test.ts b/packages/stacking/tests/stacking.test.ts index d230508e0..11b5c29bd 100644 --- a/packages/stacking/tests/stacking.test.ts +++ b/packages/stacking/tests/stacking.test.ts @@ -1,6 +1,5 @@ import { bigIntToBytes, bytesToHex, hexToBytes } from '@stacks/common'; import { base58CheckDecode } from '@stacks/encryption'; -import { StacksMainnet, StacksTestnet } from '@stacks/network'; import { AnchorMode, ClarityType, diff --git a/packages/stacking/tsconfig.build.json b/packages/stacking/tsconfig.build.json index 8d57d415d..039ff6365 100644 --- a/packages/stacking/tsconfig.build.json +++ b/packages/stacking/tsconfig.build.json @@ -8,6 +8,9 @@ "composite": true }, "references": [ + { + "path": "../api/tsconfig.build.json" + }, { "path": "../common/tsconfig.build.json" }, @@ -21,7 +24,5 @@ "path": "../transactions/tsconfig.build.json" } ], - "include": [ - "src/**/*" - ] + "include": ["src/**/*"] } diff --git a/packages/transactions/src/types.ts b/packages/transactions/src/types.ts index 9f89a41c3..5936326c4 100644 --- a/packages/transactions/src/types.ts +++ b/packages/transactions/src/types.ts @@ -55,8 +55,8 @@ import { addressHashModeToVersion, addressFromVersionHash, } from './common'; -import { deserializeCV, serializeCV } from './clarity'; -import { TransactionVersion } from '@stacks/network'; +import { ClarityValue, deserializeCV, serializeCV } from './clarity'; +import { StacksNetwork, StacksNetworkName, TransactionVersion } from '@stacks/network'; export type StacksMessage = | Address @@ -502,7 +502,7 @@ export type NoSuchContractRejection = { export type NoSuchPublicFunctionRejection = { reason: 'NoSuchPublicFunction'; -}; +} & BaseRejection; export type BadFunctionArgumentRejection = { reason: 'BadFunctionArgument'; @@ -599,3 +599,24 @@ export interface FeeEstimateResponse { estimated_cost_scalar: bigint; estimations: [FeeEstimation, FeeEstimation, FeeEstimation]; } + +/** + * Read only function options + * + * @param {String} contractAddress - the c32check address of the contract + * @param {String} contractName - the contract name + * @param {String} functionName - name of the function to be called + * @param {[ClarityValue]} functionArgs - an array of Clarity values as arguments to the function call + * @param {StacksNetwork} network - the Stacks blockchain network this transaction is destined for + * @param {String} senderAddress - the c32check address of the sender + */ +export interface ReadOnlyFunctionOptions { + contractName: string; + contractAddress: string; + functionName: string; + functionArgs: ClarityValue[]; + /** the network that the contract which contains the function is deployed to */ + network?: StacksNetworkName | StacksNetwork; + /** address of the sender */ + senderAddress: string; +} diff --git a/packages/transactions/src/utils.ts b/packages/transactions/src/utils.ts index 781d676e3..d6130ec9b 100644 --- a/packages/transactions/src/utils.ts +++ b/packages/transactions/src/utils.ts @@ -13,9 +13,7 @@ import { import { c32addressDecode } from 'c32check'; import lodashCloneDeep from 'lodash.clonedeep'; import { ClarityValue, deserializeCV, serializeCV } from './clarity'; -import { deriveDefaultUrl } from '@stacks/network/src'; -import { StacksNetworkName } from '@stacks/network'; -import { StacksNetwork } from '@stacks/network'; +import { StacksNetwork, deriveDefaultUrl, StacksNetworkName } from '@stacks/network'; // Export verify as utility method for signature verification export { verify as verifySignature } from '@noble/secp256k1';