diff --git a/package.json b/package.json index 261aa63..2b23632 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,6 @@ "@secata-public/bitmanipulation-ts": "^3.4.0", "bip32-path": "^0.4.2", "partisia-blockchain-applications-crypto": "^1.0.34", - "partisia-blockchain-applications-rpc": "^1.0.13", "partisia-blockchain-applications-sdk": "^0.1.4" }, "devDependencies": { diff --git a/src/interface.ts b/src/interface.ts index 104b772..cc57867 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -1,7 +1,6 @@ /* eslint-disable no-unused-vars */ import type { BN, ContractAbi, ScValueStruct } from "@partisiablockchain/abi-client" -import type { IContractInfo } from "partisia-blockchain-applications-rpc/lib/main/accountInfo" import type PartisiaSdk from "partisia-blockchain-applications-sdk" import type LedgerTransport from "@ledgerhq/hw-transport" import type { BYOCSymbol } from "./providers" @@ -167,8 +166,21 @@ export interface ITransactionIntent { export type MetaNamesState = ScValueStruct -export type RawContractData = Pick & { serializedContract: { avlTrees: AvlTree[] } } -export type ContractData = Pick & { serializedContract: { avlTrees?: Map } }; +/** + * A contract as returned by the reader node. Previously `IContractInfo` from + * `partisia-blockchain-applications-rpc`; only these two fields were ever read. + */ +export interface ContractInfo { + abi: string + serializedContract?: { + state: { + data: string + } + } +} + +export type RawContractData = Pick & { serializedContract: { avlTrees: AvlTree[] } } +export type ContractData = Pick & { serializedContract: { avlTrees?: Map } }; export interface ContractParams { diff --git a/src/repositories/contract-repository.ts b/src/repositories/contract-repository.ts index b9128fc..8c723ab 100644 --- a/src/repositories/contract-repository.ts +++ b/src/repositories/contract-repository.ts @@ -1,26 +1,25 @@ import { AbiParser, ContractAbi, FileAbi, StateReader } from '@partisiablockchain/abi-client' -import { PartisiaAccount } from 'partisia-blockchain-applications-rpc' -import { IPartisiaRpcConfig, PartisiaAccountClass } from 'partisia-blockchain-applications-rpc/lib/main/accountInfo' import { ByocCoin, Contract, ContractData, ContractEntry, ContractParams, GasCost, IContractRepository, ITransactionIntent, RawContractData, TransactionParams } from '../interface' import { Enviroment } from '../providers' import { SecretsProvider } from '../providers/secrets' import { convertAvlTree as convertAvlTrees } from './helpers/contract' import { AvlClient } from './helpers/avl-client' import { getRequest, promiseRetry } from './helpers/client' +import { ShardedClient, ShardedClientConfig } from './helpers/sharded-client' /** * Contract repository to interact with smart contracts on Partisia */ export class ContractRepository implements IContractRepository { - private rpc: PartisiaAccountClass + private rpc: ShardedClient private contractRegistry: Map private hostUrl: string protected avlClient: AvlClient - constructor(rpc: IPartisiaRpcConfig, private environment: Enviroment, private secrets: SecretsProvider, private ttl: number, protected hasProxyContract: boolean) { + constructor(rpc: ShardedClientConfig, private environment: Enviroment, private secrets: SecretsProvider, private ttl: number, protected hasProxyContract: boolean) { this.contractRegistry = new Map() - this.rpc = PartisiaAccount(rpc) + this.rpc = new ShardedClient(rpc) this.hostUrl = rpc.urlBaseGlobal.url this.avlClient = new AvlClient(this.hostUrl, rpc.urlBaseShards.map((shard) => shard.shard_id)) } diff --git a/src/repositories/contracts/meta-names-contract-repository.ts b/src/repositories/contracts/meta-names-contract-repository.ts index b012d71..805ab63 100644 --- a/src/repositories/contracts/meta-names-contract-repository.ts +++ b/src/repositories/contracts/meta-names-contract-repository.ts @@ -1,10 +1,10 @@ import { ContractAbi } from "@partisiablockchain/abi-client" -import { IPartisiaRpcConfig } from "partisia-blockchain-applications-rpc/lib/main/accountInfo" import { Contract, ContractParams, GetStateParams, IMetaNamesContractRepository, ITransactionIntent, MetaNamesAvlTrees, MetaNamesState, TransactionParams } from "../../interface" import { Enviroment } from "../../providers" import { SecretsProvider } from "../../providers/secrets" import { ContractRepository } from "../contract-repository" import { getAddressFromProxyContractState } from "../helpers/contract" +import { ShardedClientConfig } from "../helpers/sharded-client" /** @@ -15,7 +15,7 @@ import { getAddressFromProxyContractState } from "../helpers/contract" export class MetaNamesContractRepository extends ContractRepository implements IMetaNamesContractRepository { private proxyAddress: string - constructor(contractAddress: string, rpc: IPartisiaRpcConfig, environment: Enviroment, secrets: SecretsProvider, ttl: number, hasProxyContract: boolean) { + constructor(contractAddress: string, rpc: ShardedClientConfig, environment: Enviroment, secrets: SecretsProvider, ttl: number, hasProxyContract: boolean) { super(rpc, environment, secrets, ttl, hasProxyContract) this.proxyAddress = contractAddress } diff --git a/src/repositories/helpers/client.ts b/src/repositories/helpers/client.ts index 59e75de..dcdf883 100644 --- a/src/repositories/helpers/client.ts +++ b/src/repositories/helpers/client.ts @@ -1,8 +1,13 @@ -const getHeaders = { +const jsonHeaders = { Accept: "application/json, text/plain, */*", } -export type RequestType = "GET" +const jsonBodyHeaders = { + ...jsonHeaders, + "Content-Type": "application/json", +} + +export type RequestType = "GET" | "POST" | "PUT" /** * Requests that never settle would otherwise pin a retry chain open forever, @@ -10,22 +15,37 @@ export type RequestType = "GET" */ export const DEFAULT_TIMEOUT_MS = 30_000 -function buildOptions(method: RequestType, headers: Record, signal: AbortSignal) { - const result = { method, headers, signal } +function buildOptions(method: RequestType, headers: Record, signal: AbortSignal, body?: unknown) { + const result: { method: RequestType, headers: Record, signal: AbortSignal, body?: string } = { method, headers, signal } + if (body !== undefined) result.body = JSON.stringify(body) return result } export function getRequest(url: string, timeoutMs = DEFAULT_TIMEOUT_MS): Promise { - return handleFetch(promiseRetry(() => fetchWithTimeout(url, timeoutMs))) + return handleFetch(promiseRetry(() => fetchWithTimeout(url, "GET", jsonHeaders, undefined, timeoutMs))) +} + +export function postRequest(url: string, body: unknown, timeoutMs = DEFAULT_TIMEOUT_MS): Promise { + return handleFetch(promiseRetry(() => fetchWithTimeout(url, "POST", jsonBodyHeaders, body, timeoutMs))) +} + +/** + * Sends a request without retrying. Used where a retry would resubmit a + * side effect, such as broadcasting a transaction. + */ +export async function putRequestOnce(url: string, body: unknown, timeoutMs = DEFAULT_TIMEOUT_MS): Promise { + const response = await fetchWithTimeout(url, "PUT", jsonBodyHeaders, body, timeoutMs) + + return response.ok } -async function fetchWithTimeout(url: string, timeoutMs: number): Promise { +async function fetchWithTimeout(url: string, method: RequestType, headers: Record, body: unknown, timeoutMs: number): Promise { const controller = new AbortController() const timer = setTimeout(() => controller.abort(), timeoutMs) try { - return await fetch(url, buildOptions("GET", getHeaders, controller.signal)) + return await fetch(url, buildOptions(method, headers, controller.signal, body)) } finally { clearTimeout(timer) } diff --git a/src/repositories/helpers/sharded-client.ts b/src/repositories/helpers/sharded-client.ts new file mode 100644 index 0000000..ecd2c21 --- /dev/null +++ b/src/repositories/helpers/sharded-client.ts @@ -0,0 +1,187 @@ +import { Buffer } from "buffer" +import { getRequest, postRequest, putRequestOnce } from "./client" + +export interface ShardedClientConfig { + urlBaseGlobal: { url: string, shard_id: number } + urlBaseShards: { url: string, shard_id: number }[] +} + +export interface AccountInfo { + nonce?: number +} + +export interface TransactionInfo { + identifier: string + executionSucceeded: boolean + finalized: boolean + events: { identifier: string, destinationShard: string }[] + failureCause?: { errorMessage: string } +} + +export interface GlobalCoins { + coins: { + symbol: string + conversionRate: { numerator: string, denominator: string } + }[] +} + +export interface EventTrace { + hasError: boolean + errorMessage?: string + eventTrace: { txHash: string, shardId: number }[] +} + +/** + * Minimal reader-node client for the Partisia REST API. + * + * Replaces `partisia-blockchain-applications-rpc`, which is unmaintained (last + * published 2024-03-18) and pulled axios in for what are plain GET/POST/PUT + * calls. The endpoints and the shard derivation below match that package's + * behaviour exactly; see the notes on each method. + */ +export class ShardedClient { + private readonly globalUrl: string + private readonly shards: { url: string, shard_id: number }[] + + constructor(config: ShardedClientConfig) { + this.globalUrl = config.urlBaseGlobal.url + this.shards = config.urlBaseShards + } + + /** + * Derive which shard an address lives on. + * + * Port of `PartisiaAccountClass.deriveShardId`, itself a port of the core + * dashboard's `ShardedClient.ts`: the big-endian int32 at byte offset 17 of + * the address, modulo the shard count. + */ + deriveShardId(address: string | Buffer): number { + const buf = typeof address === 'string' ? Buffer.from(address, 'hex') : address + const int32 = Math.abs(buf.readInt32BE(17)) + + return int32 % this.shards.length + } + + shardUrl(shardId: number): string { + const shard = this.shards.find((s) => s.shard_id === shardId) + if (!shard) throw new Error(`Unknown shard ${shardId}`) + + return shard.url + } + + shardUrlForAddress(address: string): string { + return this.shardUrl(this.deriveShardId(address)) + } + + /** + * An address with no on-chain account has no nonce; the chain treats the + * first transaction from it as nonce 1, so a missing account is not an error. + */ + async getNonce(address: string, shardId?: number): Promise { + const url = this.shardUrl(shardId ?? this.deriveShardId(address)) + const account = await getRequest(`${url}/blockchain/account/${address}`) + + return account?.nonce ?? 1 + } + + async fetchCoins(): Promise { + const coins = await postRequest( + `${this.globalUrl}/blockchain/accountPlugin/global`, + { path: [{ type: "field", name: "coins" }] } + ) + if (!coins) throw new Error('Unable to fetch coins') + + return coins + } + + /** + * A transaction hash does not encode its shard, so with no `shardId` every + * shard is queried and the first that knows the transaction wins. This is + * what the rpc package did, and callers such as the event-trace walker rely + * on it. + */ + async getTransaction(transactionHash: string, shardId?: number, requireFinal = false): Promise { + const path = `/blockchain/transaction/${transactionHash}?requireFinal=${requireFinal}` + + if (shardId !== undefined) { + return getRequest(`${this.shardUrl(shardId)}${path}`) + } + + const results = await Promise.all( + this.shards.map((shard) => + getRequest(`${shard.url}${path}`).catch(() => undefined) + ) + ) + + return results.find((transaction) => transaction !== undefined) + } + + broadcastTransaction(addressFrom: string, payload: string | Buffer): Promise { + const url = this.shardUrlForAddress(addressFrom) + const transactionPayload = typeof payload === 'string' ? payload : payload.toString('base64') + + return putRequestOnce(`${url}/blockchain/transaction`, { transactionPayload }) + } + + /** + * Walk a transaction and every event it spawned, collecting failures. + * + * Mirrors `PartisiaAccountClass.getTransactionEventTrace`. Spawned events + * land on the shard named in `destinationShard` ("Shard1" -> 1), which is why + * each recursive lookup re-targets rather than reusing the parent's shard. + */ + async getTransactionEventTrace(transactionHash: string, shardId?: number): Promise { + const transaction = await this.pollTransaction(transactionHash, shardId) + + const result: EventTrace = { + hasError: !transaction.executionSucceeded, + errorMessage: transaction.executionSucceeded ? undefined : transaction.failureCause?.errorMessage, + eventTrace: transaction.events.map((event) => ({ + txHash: event.identifier, + shardId: shardIdFromDestination(event.destinationShard), + })), + } + + for (const event of transaction.events) { + await this.collectEvents(event.identifier, shardIdFromDestination(event.destinationShard), result) + } + + return result + } + + private async collectEvents(transactionHash: string, shardId: number, result: EventTrace): Promise { + const transaction = await this.pollTransaction(transactionHash, shardId) + + if (!transaction.executionSucceeded) { + result.hasError = true + result.errorMessage = transaction.failureCause?.errorMessage + } + + for (const event of transaction.events) { + const eventShardId = shardIdFromDestination(event.destinationShard) + result.eventTrace.push({ txHash: event.identifier, shardId: eventShardId }) + await this.collectEvents(event.identifier, eventShardId, result) + } + } + + /** + * The transaction is known to exist; it may not have propagated to the + * reader node yet. Retries until it is finalized. + */ + private async pollTransaction(transactionHash: string, shardId?: number, attempts = 30, intervalInMillis = 1000): Promise { + for (let attempt = 0; attempt < attempts; attempt++) { + const transaction = await this.getTransaction(transactionHash, shardId).catch(() => undefined) + + if (transaction?.finalized) return transaction + + await new Promise((resolve) => setTimeout(resolve, intervalInMillis)) + } + + throw new Error(`Transaction ${transactionHash} was not finalized in time`) + } +} + +/** "Shard1" -> 1 */ +function shardIdFromDestination(destinationShard: string): number { + return Number(destinationShard.replace('Shard', '')) +} diff --git a/src/transactions/helper.ts b/src/transactions/helper.ts index 4d31b4b..5966869 100644 --- a/src/transactions/helper.ts +++ b/src/transactions/helper.ts @@ -1,6 +1,6 @@ import type { RpcContractBuilder } from "@partisiablockchain/abi-client" -import type { PartisiaAccountClass } from "partisia-blockchain-applications-rpc/lib/main/accountInfo" -import type { PartisiaRpcClass } from "partisia-blockchain-applications-rpc/lib/main/rpc" +import type { ITransactionResult } from "../interface" +import type { ShardedClient } from "../repositories/helpers/sharded-client" export const builderToBytesBe = (rpc: RpcContractBuilder) => { return rpc.getBytes() @@ -9,7 +9,7 @@ export const builderToBytesBe = (rpc: RpcContractBuilder) => { export const getChainId = (isMainnet: boolean): string => `Partisia Blockchain${isMainnet ? '' : ' Testnet'}` export const serializeTransaction = async ( - rpc: PartisiaAccountClass, + client: ShardedClient, walletAddress: string, contractAddress: string, payload: Buffer, @@ -21,8 +21,8 @@ export const serializeTransaction = async ( // reading state never loads it. const { serializedTransaction } = await import("partisia-blockchain-applications-crypto/lib/main/transaction") - const shardId = rpc.deriveShardId(walletAddress) - const nonce = await rpc.getNonce(walletAddress, shardId) + const shardId = client.deriveShardId(walletAddress) + const nonce = await client.getNonce(walletAddress, shardId) // Need to pass a number otherwise the internal library will throw an error const validTo = (new Date().getTime() + validityInMillis) as unknown as string @@ -33,32 +33,31 @@ export const serializeTransaction = async ( ) } -export const buildTransactionResult = (rpc: PartisiaAccountClass, - rpcShard: PartisiaRpcClass, - transactionHash: string) => { +export const buildTransactionResult = ( + client: ShardedClient, + shardId: number, + transactionHash: string +) => { return { transactionHash, - fetchResult: transactionResult(rpc, rpcShard, transactionHash) + fetchResult: transactionResult(client, shardId, transactionHash) } } const transactionResult = async ( - rpc: PartisiaAccountClass, - rpcShard: PartisiaRpcClass, + client: ShardedClient, + shardId: number, transactionHash: string -) => { - const isFinalOnChain = await broadcastTransactionPoller(transactionHash, rpcShard) +): Promise => { + const isFinalOnChain = await broadcastTransactionPoller(client, shardId, transactionHash) - let transactionResult - if (isFinalOnChain) { - transactionResult = await rpc.getTransactionEventTrace(transactionHash) - } else { - transactionResult = { + const transactionResult = isFinalOnChain + ? await client.getTransactionEventTrace(transactionHash, shardId) + : { hasError: true, errorMessage: 'unable to broadcast to chain', eventTrace: [], } - } return { transactionHash, @@ -67,26 +66,23 @@ const transactionResult = async ( } const broadcastTransactionPoller = async ( - trxHash: string, - rpc: PartisiaRpcClass, - num_iter = 10, - interval_sleep = 2000 + client: ShardedClient, + shardId: number, + transactionHash: string, + attempts = 10, + intervalInMillis = 2000 ) => { - let intCounter = 0 - while (++intCounter < num_iter) { + let attempt = 0 + while (++attempt < attempts) { try { - const resTx = await rpc.getTransaction(trxHash) - if (resTx.finalized) { - break - } + const transaction = await client.getTransaction(transactionHash, shardId) + if (transaction?.finalized) break } catch (error) { if (error instanceof Error && !error.message.includes('404')) console.error(error.message) } finally { - const sleep = (ms: number) => { - return new Promise((resolve) => setTimeout(resolve, ms)) - } - await sleep(interval_sleep) + await new Promise((resolve) => setTimeout(resolve, intervalInMillis)) } } - return intCounter < num_iter + + return attempt < attempts } diff --git a/src/transactions/index.ts b/src/transactions/index.ts index 865530e..533554d 100644 --- a/src/transactions/index.ts +++ b/src/transactions/index.ts @@ -1,8 +1,7 @@ -import type { PartisiaAccountClass } from "partisia-blockchain-applications-rpc/lib/main/accountInfo" import type LedgerTransport from "@ledgerhq/hw-transport" import type { ITransactionIntent, MetaMaskSdk } from "../interface" import { buildTransactionResult, getChainId, serializeTransaction } from "./helper" -import { PartisiaRpc } from "partisia-blockchain-applications-rpc" +import type { ShardedClient } from "../repositories/helpers/sharded-client" import assert from "assert" import type PartisiaSdk from "partisia-blockchain-applications-sdk" @@ -22,7 +21,7 @@ const loadWalletCrypto = () => import("partisia-blockchain-applications-crypto/l const loadLedgerClient = () => import("./ledger") export const createTransactionFromLedgerClient = async ( - rpc: PartisiaAccountClass, + rpc: ShardedClient, transport: LedgerTransport, contractAddress: string, payload: Buffer, @@ -37,7 +36,6 @@ export const createTransactionFromLedgerClient = async ( const client = new PartisiaLedgerClient(transport) const walletAddress: string = await client.getAddress() const shardId = rpc.deriveShardId(walletAddress) - const url = rpc.getShardUrl(shardId) const serializedTransaction = await serializeTransaction(rpc, walletAddress, contractAddress, payload, cost) const chainId = getChainId(isMainnet) @@ -49,16 +47,15 @@ export const createTransactionFromLedgerClient = async ( const transactionPayload = Buffer.concat([signatureBuffer, serializedTransaction]).toString('base64') - const rpcShard = PartisiaRpc({ baseURL: url }) const transactionHash = getTrxHash(digest, signatureBuffer) - const isValid = await rpcShard.broadcastTransaction(transactionPayload) + const isValid = await rpc.broadcastTransaction(walletAddress, transactionPayload) assert(isValid, 'Unknown Error') - return buildTransactionResult(rpc, rpcShard, transactionHash) + return buildTransactionResult(rpc, shardId, transactionHash) } export const createTransactionFromMetaMaskClient = async ( - rpc: PartisiaAccountClass, + rpc: ShardedClient, client: MetaMaskSdk, contractAddress: string, payload: Buffer, @@ -73,7 +70,6 @@ export const createTransactionFromMetaMaskClient = async ( params: { snapId, request: { method: "get_address" } }, }) const shardId = rpc.deriveShardId(walletAddress) - const url = rpc.getShardUrl(shardId) const serializedTransaction = await serializeTransaction(rpc, walletAddress, contractAddress, payload, cost) const chainId = getChainId(isMainnet) @@ -100,16 +96,15 @@ export const createTransactionFromMetaMaskClient = async ( const transactionPayload = Buffer.concat([signature, serializedTransaction]).toString('base64') - const rpcShard = PartisiaRpc({ baseURL: url }) const transactionHash = getTrxHash(digest, signature) - const isValid = await rpcShard.broadcastTransaction(transactionPayload) + const isValid = await rpc.broadcastTransaction(walletAddress, transactionPayload) assert(isValid, 'Unknown Error') - return buildTransactionResult(rpc, rpcShard, transactionHash) + return buildTransactionResult(rpc, shardId, transactionHash) } export const createTransactionFromPartisiaClient = async ( - rpc: PartisiaAccountClass, + rpc: ShardedClient, client: PartisiaSdk, contractAddress: string, payload: Buffer, @@ -127,10 +122,8 @@ export const createTransactionFromPartisiaClient = async ( }) const shardId = rpc.deriveShardId(walletAddress) - const url = rpc.getShardUrl(shardId) - const rpcShard = PartisiaRpc({ baseURL: url }) - return buildTransactionResult(rpc, rpcShard, transaction.trxHash) + return buildTransactionResult(rpc, shardId, transaction.trxHash) } /** @@ -144,7 +137,7 @@ export const createTransactionFromPartisiaClient = async ( const BROADCAST_ATTEMPTS = 3 export const createTransactionFromPrivateKey = async ( - rpc: PartisiaAccountClass, + rpc: ShardedClient, contractAddress: string, privateKey: string, payload: Buffer, @@ -158,8 +151,6 @@ export const createTransactionFromPrivateKey = async ( const walletAddress = privateKeyToAccountAddress(privateKey) const shardId = rpc.deriveShardId(walletAddress) - const url = rpc.getShardUrl(shardId) - const rpcShard = PartisiaRpc({ baseURL: url }) let lastError: unknown for (let attempt = 0; attempt < BROADCAST_ATTEMPTS; attempt++) { @@ -177,10 +168,10 @@ export const createTransactionFromPrivateKey = async ( const transactionHash = getTrxHash(digest, signature) try { - const isValid = await rpcShard.broadcastTransaction(trx) + const isValid = await rpc.broadcastTransaction(walletAddress, trx) assert(isValid, 'Unknown Error') - return buildTransactionResult(rpc, rpcShard, transactionHash) + return buildTransactionResult(rpc, shardId, transactionHash) } catch (error) { lastError = error } diff --git a/yarn.lock b/yarn.lock index 88d4e05..972ab9d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1007,13 +1007,6 @@ acorn@^8.11.0, acorn@^8.4.1, acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.18.0.tgz#4faf01b2d6d326bfeed97aea1f52220b5f4c1940" integrity sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ== -agent-base@6: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - ajv@^6.12.4: version "6.15.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.15.0.tgz#07e982c74626167aa7a2495c53817892d7139492" @@ -1156,11 +1149,6 @@ async-function@^1.0.0: resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b" integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - available-typed-arrays@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" @@ -1168,16 +1156,6 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" -axios@^1.6.2: - version "1.20.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.20.0.tgz#515513445aa60e71d04b6521ca6210829ccb4786" - integrity sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg== - dependencies: - follow-redirects "^1.16.0" - form-data "^4.0.6" - https-proxy-agent "^5.0.1" - proxy-from-env "^2.1.0" - babel-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" @@ -1516,13 +1494,6 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - convert-source-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" @@ -1615,13 +1586,6 @@ data-view-byte-offset@^1.0.1: es-errors "^1.3.0" is-data-view "^1.0.1" -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.4.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" - integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== - dependencies: - ms "^2.1.3" - debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -1629,6 +1593,13 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + dedent@^1.0.0: version "1.7.2" resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.7.2.tgz#34e2264ab538301e27cf7b07bf2369c19baa8dd9" @@ -1662,11 +1633,6 @@ define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -2233,11 +2199,6 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.4.4.tgz#aeeca2a506303f0cee61c59e6c9f2a88d2f29fc6" integrity sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q== -follow-redirects@^1.16.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.16.0.tgz#28474a159d3b9d11ef62050a14ed60e4df6d61bc" - integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw== - for-each@^0.3.3, for-each@^0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" @@ -2245,17 +2206,6 @@ for-each@^0.3.3, for-each@^0.3.5: dependencies: is-callable "^1.2.7" -form-data@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.6.tgz#28e864e1b786dbebb68db1f452f9635278665827" - integrity sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - es-set-tostringtag "^2.1.0" - hasown "^2.0.4" - mime-types "^2.1.35" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -2504,14 +2454,6 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -https-proxy-agent@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -3426,18 +3368,6 @@ micromatch@^4.0.4, micromatch@^4.0.8: braces "^3.0.3" picomatch "^2.3.1" -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.35: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -3686,13 +3616,6 @@ partisia-blockchain-applications-crypto@^1.0.23, partisia-blockchain-application merkletreejs "^0.3.11" zxcvbn "^4.4.2" -partisia-blockchain-applications-rpc@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/partisia-blockchain-applications-rpc/-/partisia-blockchain-applications-rpc-1.0.13.tgz#5d1ad46ef2d440769ba9d9f05a294b3d3f3500a6" - integrity sha512-4W1RLkIzruhBMql4Ls7W2n2oIEiGhpbVy3g78QOw/Eb8BX6xIBHUmkf4q2ldBcTN7bs5UQROvhKyksfPKGbXng== - dependencies: - axios "^1.6.2" - partisia-blockchain-applications-sdk@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/partisia-blockchain-applications-sdk/-/partisia-blockchain-applications-sdk-0.1.4.tgz#3b8f488651e02b8beb7abb045dcb2c602948b246" @@ -3781,11 +3704,6 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -proxy-from-env@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz#a7487568adad577cfaaa7e88c49cab3ab3081aba" - integrity sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA== - punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"