diff --git a/docs/README_TYPEDOC.md b/docs/README_TYPEDOC.md index 3d3924a7ce..d23dddeae1 100644 --- a/docs/README_TYPEDOC.md +++ b/docs/README_TYPEDOC.md @@ -18,27 +18,27 @@ NEAR JavaScript API is a complete library to interact with the NEAR blockchain. ### Connect to NEAR -- [From the browser](modules/near_api_js.browserConnect.html) -- [From Node.js](modules/near_api_js.connect.html) +- [From the browser](https://near.github.io/near-api-js/modules/near_api_js.browserConnect.html) +- [From Node.js](https://near.github.io/near-api-js/modules/near_api_js.connect.html) ### Managing Accounts -- Class [`Account`](classes/_near_js_accounts.account.Account.html) -- Module [`walletAccount`](modules/_near_js_wallet_account.walletAccount.html) -- Class [`Contract`](classes/_near_js_accounts.contract.Contract.html) +- Class [`Account`](https://near.github.io/near-api-js/classes/near_api_js.account.Account.html) +- Module [`walletAccount`](https://near.github.io/near-api-js/modules/_near_js_wallet_account.walletAccount.html) +- Class [`Contract`](https://near.github.io/near-api-js/classes/_near_js_accounts.contract.Contract.html) ### Managing Keys -- Module [`utils/key_pair`](modules/near_api_js.utils_key_pair.html) -- Class [`InMemoryKeyStore`](classes/_near_js_keystores.in_memory_key_store.InMemoryKeyStore.html) -- Class [`UnencryptedFileSystemKeyStore`](classes/_near_js_keystores_node.unencrypted_file_system_keystore.UnencryptedFileSystemKeyStore.html) -- Class [`MergeKeyStore`](classes/_near_js_keystores.merge_key_store.MergeKeyStore.html) +- Module [`utils/key_pair`](https://near.github.io/near-api-js/modules/near_api_js.utils_key_pair.html) +- Class [`InMemoryKeyStore`](https://near.github.io/near-api-js/classes/_near_js_keystores.in_memory_key_store.InMemoryKeyStore.html) +- Class [`UnencryptedFileSystemKeyStore`](https://near.github.io/near-api-js/classes/_near_js_keystores_node.unencrypted_file_system_keystore.UnencryptedFileSystemKeyStore.html) +- Class [`MergeKeyStore`](https://near.github.io/near-api-js/classes/_near_js_keystores.merge_key_store.MergeKeyStore.html) ### RPC -- [Request and Response Types](modules/_near_js_types.provider.html) -- [Client](classes/_near_js_providers.json_rpc_provider.JsonRpcProvider.html) +- [Request and Response Types](https://near.github.io/near-api-js/modules/near_api_js.providers_provider.html) +- [Client](https://near.github.io/near-api-js/classes/_near_js_providers.json_rpc_provider.JsonRpcProvider.html) ### Utils -- [Formatting utils](modules/_near_js_utils.format.html) +- [Formatting utils](https://near.github.io/near-api-js/modules/_near_js_utils.format.html) diff --git a/packages/accounts/package.json b/packages/accounts/package.json index 33493224e1..d5690f490b 100644 --- a/packages/accounts/package.json +++ b/packages/accounts/package.json @@ -37,7 +37,8 @@ "jest": "26.0.1", "near-hello": "0.5.1", "ts-jest": "26.5.6", - "typescript": "4.9.4" + "typescript": "4.9.4", + "near-workspaces": "3.4.0" }, "files": [ "lib" diff --git a/packages/accounts/src/account.ts b/packages/accounts/src/account.ts index 0ce11cbeda..989ae1daf3 100644 --- a/packages/accounts/src/account.ts +++ b/packages/accounts/src/account.ts @@ -209,8 +209,14 @@ export class Account { } /** - * Sign a transaction to preform a list of actions and broadcast it using the RPC API. + * Sign a transaction to perform a list of actions and broadcast it using the RPC API. * @see {@link "@near-js/providers".json-rpc-provider.JsonRpcProvider | JsonRpcProvider } + * + * @param options The options for signing and sending the transaction. + * @param options.receiverId The NEAR account ID of the transaction receiver. + * @param options.actions The list of actions to be performed in the transaction. + * @param options.returnError Whether to return an error if the transaction fails. + * @returns {Promise} A promise that resolves to the final execution outcome of the transaction. */ async signAndSendTransaction({ receiverId, actions, returnError }: SignAndSendTransactionOptions): Promise { let txHash, signedTx; @@ -382,9 +388,19 @@ export class Account { return Buffer.concat([Buffer.from(contractId), Buffer.from([0]), Buffer.from(method), Buffer.from([0]), Buffer.from(args)]); } - /** - * Execute function call - * @returns {Promise} + /** + * Execute a function call. + * @param options The options for the function call. + * @param options.contractId The NEAR account ID of the smart contract. + * @param options.methodName The name of the method to be called on the smart contract. + * @param options.args The arguments to be passed to the method. + * @param options.gas The maximum amount of gas to be used for the function call. + * @param options.attachedDeposit The amount of NEAR tokens to be attached to the function call. + * @param options.walletMeta Metadata for wallet integration. + * @param options.walletCallbackUrl The callback URL for wallet integration. + * @param options.stringify A function to convert input arguments into bytes array + * @param options.jsContract Whether the contract is from JS SDK, automatically encodes args from JS SDK to binary. + * @returns {Promise} A promise that resolves to the final execution outcome of the function call. */ async functionCall({ contractId, methodName, args = {}, gas = DEFAULT_FUNCTION_CALL_GAS, attachedDeposit, walletMeta, walletCallbackUrl, stringify, jsContract }: ChangeFunctionCallOptions): Promise { this.validateArgs(args); @@ -461,9 +477,10 @@ export class Account { /** * Compose and sign a SignedDelegate action to be executed in a transaction on behalf of this Account instance * - * @param actions Actions to be included in the meta transaction - * @param blockHeightTtl Number of blocks past the current block height for which the SignedDelegate action may be included in a meta transaction - * @param receiverId Receiver account of the meta transaction + * @param options Options for the transaction. + * @param options.actions Actions to be included in the meta transaction + * @param options.blockHeightTtl Number of blocks past the current block height for which the SignedDelegate action may be included in a meta transaction + * @param options.receiverId Receiver account of the meta transaction */ async signedDelegate({ actions, @@ -517,13 +534,14 @@ export class Account { * Invoke a contract view function using the RPC API. * @see [https://docs.near.org/api/rpc/contracts#call-a-contract-function](https://docs.near.org/api/rpc/contracts#call-a-contract-function) * - * @param viewFunctionCallOptions.contractId NEAR account where the contract is deployed - * @param viewFunctionCallOptions.methodName The view-only method (no state mutations) name on the contract as it is written in the contract code - * @param viewFunctionCallOptions.args Any arguments to the view contract method, wrapped in JSON - * @param viewFunctionCallOptions.parse Parse the result of the call. Receives a Buffer (bytes array) and converts it to any object. By default result will be treated as json. - * @param viewFunctionCallOptions.stringify Convert input arguments into a bytes array. By default the input is treated as a JSON. - * @param viewFunctionCallOptions.jsContract Is contract from JS SDK, automatically encodes args from JS SDK to binary. - * @param viewFunctionCallOptions.blockQuery specifies which block to query state at. By default returns last "optimistic" block (i.e. not necessarily finalized). + * @param options Function call options. + * @param options.contractId NEAR account where the contract is deployed + * @param options.methodName The view-only method (no state mutations) name on the contract as it is written in the contract code + * @param options.args Any arguments to the view contract method, wrapped in JSON + * @param options.parse Parse the result of the call. Receives a Buffer (bytes array) and converts it to any object. By default result will be treated as json. + * @param options.stringify Convert input arguments into a bytes array. By default the input is treated as a JSON. + * @param options.jsContract Is contract from JS SDK, automatically encodes args from JS SDK to binary. + * @param options.blockQuery specifies which block to query state at. By default returns last "optimistic" block (i.e. not necessarily finalized). * @returns {Promise} */ diff --git a/packages/accounts/src/account_2fa.ts b/packages/accounts/src/account_2fa.ts index 6bfec76ef8..c22e664a0d 100644 --- a/packages/accounts/src/account_2fa.ts +++ b/packages/accounts/src/account_2fa.ts @@ -48,6 +48,11 @@ export class Account2FA extends AccountMultisig { /** * Sign a transaction to preform a list of actions and broadcast it using the RPC API. * @see {@link "@near-js/providers".json-rpc-provider.JsonRpcProvider.sendTransaction | JsonRpcProvider.sendTransaction} + * + * @param options Options for the transaction. + * @param options.receiverId The NEAR account ID of the transaction receiver. + * @param options.actions The list of actions to be included in the transaction. + * @returns {Promise} A promise that resolves to the final execution outcome of the transaction. */ async signAndSendTransaction({ receiverId, actions }: SignAndSendTransactionOptions): Promise { await super.signAndSendTransaction({ receiverId, actions }); @@ -62,6 +67,11 @@ export class Account2FA extends AccountMultisig { // default helpers for CH deployments of multisig + /** + * Deploy a multisig contract with 2FA and handle the deployment process. + * @param contractBytes - The bytecode of the multisig contract. + * @returns {Promise} A promise that resolves to the final execution outcome of the deployment. + */ async deployMultisig(contractBytes: Uint8Array) { const { accountId } = this; @@ -100,6 +110,13 @@ export class Account2FA extends AccountMultisig { } } + /** + * Disable 2FA with the option to clean up contract state. + * @param options Options for disabling 2FA. + * @param options.contractBytes The bytecode of the contract to deploy. + * @param options.cleanupContractBytes The bytecode of the cleanup contract (optional). + * @returns {Promise} A promise that resolves to the final execution outcome of the operation. + */ async disableWithFAK({ contractBytes, cleanupContractBytes }: { contractBytes: Uint8Array; cleanupContractBytes?: Uint8Array }) { let cleanupActions = []; if(cleanupContractBytes) { @@ -123,6 +140,11 @@ export class Account2FA extends AccountMultisig { return this.signAndSendTransactionWithAccount(this.accountId, actions); } + /** + * Retrieves cleanup actions for disabling 2FA. + * @param cleanupContractBytes - The bytecode of the cleanup contract. + * @returns {Promise} - A promise that resolves to an array of cleanup actions. + */ async get2faDisableCleanupActions(cleanupContractBytes: Uint8Array) { const currentAccountState: { key: Buffer; value: Buffer }[] = await this.viewState('').catch(error => { const cause = error.cause && error.cause.name; @@ -141,6 +163,10 @@ export class Account2FA extends AccountMultisig { ] : []; } + /** + * Retrieves key conversion actions for disabling 2FA. + * @returns {Promise} - A promise that resolves to an array of key conversion actions. + */ async get2faDisableKeyConversionActions() { const { accountId } = this; const accessKeys = await this.getAccessKeys(); @@ -163,7 +189,8 @@ export class Account2FA extends AccountMultisig { /** * This method converts LAKs back to FAKs, clears state and deploys an 'empty' contract (contractBytes param) * @param [contractBytes]{@link https://github.com/near/near-wallet/blob/master/packages/frontend/src/wasm/main.wasm?raw=true} - * @param [cleanupContractBytes]{@link https://github.com/near/core-contracts/blob/master/state-cleanup/res/state_cleanup.wasm?raw=true} + * @param [cleanupContractBytes]{@link https://github.com/near/core-contracts/blob/master/state-manipulation/res/state_cleanup.wasm?raw=true} + * @returns {Promise} A promise that resolves to the final execution outcome of the operation. */ async disable(contractBytes: Uint8Array, cleanupContractBytes: Uint8Array) { const { stateStatus } = await this.checkMultisigCodeAndStateStatus(); @@ -193,6 +220,10 @@ export class Account2FA extends AccountMultisig { }); } + /** + * Default implementation for sending the 2FA code. + * @returns {Promise} - A promise that resolves to the request ID. + */ async sendCodeDefault() { const { accountId } = this; const { requestId } = this.getRequest(); @@ -209,6 +240,10 @@ export class Account2FA extends AccountMultisig { throw new Error('There is no getCode callback provided. Please provide your own in AccountMultisig constructor options. It has a parameter method where method.kind is "email" or "phone".'); } + /** + * Prompts the user to enter and verify the 2FA code. + * @returns {Promise} - A promise that resolves to the verification result. + */ async promptAndVerify() { const method = await this.get2faMethod(); const securityCode = await this.getCode(method); @@ -227,6 +262,11 @@ export class Account2FA extends AccountMultisig { } } + /** + * Verify the 2FA code using the default method. + * @param securityCode - The security code to verify. + * @returns {Promise} A promise that resolves to the verification result. + */ async verifyCodeDefault(securityCode: string) { const { accountId } = this; const request = this.getRequest(); @@ -241,6 +281,10 @@ export class Account2FA extends AccountMultisig { }); } + /** + * Retrieves recovery methods for the account. + * @returns {Promise<{ accountId: string, data: any }>} - A promise that resolves to recovery methods data. + */ async getRecoveryMethods() { const { accountId } = this; return { @@ -249,6 +293,10 @@ export class Account2FA extends AccountMultisig { }; } + /** + * Gets the 2FA method (kind and detail). + * @returns {Promise<{ kind: string, detail: string }>} A promise that resolves to the 2FA method. + */ async get2faMethod() { let { data } = await this.getRecoveryMethods(); if (data && data.length) { @@ -259,6 +307,10 @@ export class Account2FA extends AccountMultisig { return { kind, detail }; } + /** + * Generates a signature for the latest finalized block. + * @returns {Promise<{ blockNumber: string, blockNumberSignature: string }>} - A promise that resolves to the signature information. + */ async signatureFor() { const { accountId } = this; const block = await this.connection.provider.block({ finality: 'final' }); @@ -268,6 +320,12 @@ export class Account2FA extends AccountMultisig { return { blockNumber, blockNumberSignature }; } + /** + * Sends a signed JSON request to a specified path. + * @param path - The path for the request. + * @param body - The request body. + * @returns {Promise} - A promise that resolves to the response from the helper. + */ async postSignedJson(path, body) { return await fetchJson(this.helperUrl + path, JSON.stringify({ ...body, diff --git a/packages/accounts/src/account_multisig.ts b/packages/accounts/src/account_multisig.ts index c159b4b70c..a7d92a5486 100644 --- a/packages/accounts/src/account_multisig.ts +++ b/packages/accounts/src/account_multisig.ts @@ -30,16 +30,37 @@ export class AccountMultisig extends Account { public storage: any; public onAddRequestResult: (any) => any; + /** + * Constructs an instance of the `AccountMultisig` class. + * @param connection The NEAR connection object. + * @param accountId The NEAR account ID. + * @param options Additional options for the multisig account. + * @param options.storage Storage to store data related to multisig operations. + * @param options.onAddRequestResult Callback function to handle the result of adding a request. + */ constructor(connection: Connection, accountId: string, options: any) { super(connection, accountId); this.storage = options.storage; this.onAddRequestResult = options.onAddRequestResult; } + /** + * Sign and send a transaction with the multisig account as the sender. + * @param receiverId - The NEAR account ID of the transaction receiver. + * @param actions - The list of actions to be included in the transaction. + * @returns {Promise} A promise that resolves to the final execution outcome of the transaction. + */ async signAndSendTransactionWithAccount(receiverId: string, actions: Action[]): Promise { return super.signAndSendTransaction({ receiverId, actions }); } + /** + * Sign and send a multisig transaction to add a request and confirm it. + * @param options Options for the multisig transaction. + * @param options.receiverId The NEAR account ID of the transaction receiver. + * @param options.actions The list of actions to be included in the transaction. + * @returns {Promise} A promise that resolves to the final execution outcome of the transaction. + */ async signAndSendTransaction({ receiverId, actions }: SignAndSendTransactionOptions): Promise { const { accountId } = this; @@ -91,10 +112,12 @@ export class AccountMultisig extends Account { return result; } - /* + /** * This method submits a canary transaction that is expected to always fail in order to determine whether the contract currently has valid multisig state * and whether it is initialized. The canary transaction attempts to delete a request at index u32_max and will go through if a request exists at that index. * a u32_max + 1 and -1 value cannot be used for the canary due to expected u32 error thrown before deserialization attempt. + * @param contractBytes The bytecode of the multisig contract. + * @returns {Promise<{ codeStatus: MultisigCodeStatus; stateStatus: MultisigStateStatus }>} A promise that resolves to the status of the code and state. */ async checkMultisigCodeAndStateStatus(contractBytes?: Uint8Array): Promise<{ codeStatus: MultisigCodeStatus; stateStatus: MultisigStateStatus }> { const u32_max = 4_294_967_295; @@ -128,6 +151,11 @@ export class AccountMultisig extends Account { } } + /** + * Delete a multisig request by its ID. + * @param request_id The ID of the multisig request to be deleted. + * @returns {Promise} A promise that resolves to the final execution outcome of the deletion. + */ deleteRequest(request_id) { return super.signAndSendTransaction({ receiverId: this.accountId, @@ -135,6 +163,10 @@ export class AccountMultisig extends Account { }); } + /** + * Delete all multisig requests associated with the account. + * @returns {Promise} A promise that resolves when all requests are deleted. + */ async deleteAllRequests() { const request_ids = await this.getRequestIds(); if(request_ids.length) { @@ -142,6 +174,10 @@ export class AccountMultisig extends Account { } } + /** + * Delete unconfirmed multisig requests associated with the account. + * @returns {Promise} A promise that resolves when unconfirmed requests are deleted. + */ async deleteUnconfirmedRequests () { // TODO: Delete in batch, don't delete unexpired // TODO: Delete in batch, don't delete unexpired (can reduce gas usage dramatically) diff --git a/packages/accounts/src/local-view-execution/index.ts b/packages/accounts/src/local-view-execution/index.ts index d231c9a408..66af734a00 100644 --- a/packages/accounts/src/local-view-execution/index.ts +++ b/packages/accounts/src/local-view-execution/index.ts @@ -64,6 +64,15 @@ export class LocalViewExecution { return fetched; } + /** + * Calls a view function on a contract, fetching the contract code and state if needed. + * @param options Options for calling the view function. + * @param options.contractId The contract account ID. + * @param options.methodName The name of the view function to call. + * @param options.args The arguments to pass to the view function. + * @param options.blockQuery The block query options. + * @returns {Promise} - A promise that resolves to the result of the view function. + */ public async viewFunction({ contractId, methodName, args = {}, blockQuery = { finality: 'optimistic' }, ...ignored }: ViewFunctionCallOptions) { const methodArgs = JSON.stringify(args); diff --git a/packages/accounts/test/config.js b/packages/accounts/test/config.js index 1734592c63..23f994a1dd 100644 --- a/packages/accounts/test/config.js +++ b/packages/accounts/test/config.js @@ -1,4 +1,7 @@ -module.exports = function getConfig(env) { +const { Worker } = require('near-workspaces'); +const fs = require('fs'); +let worker; +module.exports = async function getConfig(env) { switch (env) { case 'production': case 'mainnet': @@ -32,12 +35,17 @@ module.exports = function getConfig(env) { walletUrl: 'http://localhost:4000/wallet', }; case 'test': - case 'ci': + case 'ci': { + if (!worker) worker = await Worker.init(); + const keyFile = fs.readFileSync(`${worker.rootAccount.manager.config.homeDir}/validator_key.json`); + const keyPair = JSON.parse(keyFile.toString()); return { - networkId: 'shared-test', - nodeUrl: 'https://rpc.ci-testnet.near.org', - masterAccount: 'test.near', + networkId: worker.config.network, + nodeUrl: worker.manager.config.rpcAddr, + masterAccount: worker.rootAccount._accountId, + secretKey: keyPair.secret_key || keyPair.private_key }; + } default: throw Error(`Unconfigured environment '${env}'. Can be configured in src/config.js.`); } diff --git a/packages/accounts/test/providers.test.js b/packages/accounts/test/providers.test.js index 67b39cc660..ca6dec7e71 100644 --- a/packages/accounts/test/providers.test.js +++ b/packages/accounts/test/providers.test.js @@ -1,4 +1,3 @@ -const { JsonRpcProvider } = require('@near-js/providers'); const BN = require('bn.js'); const base58 = require('bs58'); @@ -6,186 +5,186 @@ const testUtils = require('./test-utils'); jest.setTimeout(20000); -const withProvider = (fn) => { - const config = Object.assign(require('./config')(process.env.NODE_ENV || 'test')); - const provider = new JsonRpcProvider(config.nodeUrl); - return () => fn(provider); -}; +describe('providers', () => { + let provider; + let near; -test('txStatus with string hash and buffer hash', withProvider(async (provider) => { - const near = await testUtils.setUpTestConnection(); - const sender = await testUtils.createAccount(near); - const receiver = await testUtils.createAccount(near); - const outcome = await sender.sendMoney(receiver.accountId, new BN('1')); - - const responseWithString = await provider.txStatus(outcome.transaction.hash, sender.accountId); - const responseWithUint8Array = await provider.txStatus(base58.decode(outcome.transaction.hash), sender.accountId); - expect(responseWithString).toMatchObject(outcome); - expect(responseWithUint8Array).toMatchObject(outcome); -})); - -test('txStatusReciept with string hash and buffer hash', withProvider(async (provider) => { - const near = await testUtils.setUpTestConnection(); - const sender = await testUtils.createAccount(near); - const receiver = await testUtils.createAccount(near); - const outcome = await sender.sendMoney(receiver.accountId, new BN('1')); - const reciepts = await provider.sendJsonRpc('EXPERIMENTAL_tx_status', [outcome.transaction.hash, sender.accountId]); - - const responseWithString = await provider.txStatusReceipts(outcome.transaction.hash, sender.accountId); - const responseWithUint8Array = await provider.txStatusReceipts(base58.decode(outcome.transaction.hash), sender.accountId); - expect('transaction_outcome' in responseWithString).toBeTruthy(); - expect('logs' in responseWithString.transaction_outcome.outcome).toBeTruthy(); - expect('receipt_ids' in responseWithString.transaction_outcome.outcome).toBeTruthy(); - expect('gas_burnt' in responseWithString.transaction_outcome.outcome).toBeTruthy(); - expect('tokens_burnt' in responseWithString.transaction_outcome.outcome).toBeTruthy(); - expect('executor_id' in responseWithString.transaction_outcome.outcome).toBeTruthy(); - expect('status' in responseWithString.transaction_outcome.outcome).toBeTruthy(); - expect(responseWithString).toMatchObject(reciepts); - expect(responseWithUint8Array).toMatchObject(reciepts); -})); - -test('json rpc query account', withProvider(async (provider) => { - const near = await testUtils.setUpTestConnection(); - const account = await testUtils.createAccount(near); - let response = await provider.query(`account/${account.accountId}`, ''); - expect(response.code_hash).toEqual('11111111111111111111111111111111'); -})); - -test('json rpc query view_state', withProvider(async (provider) => { - const near = await testUtils.setUpTestConnection(); - const account = await testUtils.createAccount(near); - const contract = await testUtils.deployContract(account, testUtils.generateUniqueString('test')); - - await contract.setValue({ args: { value: 'hello' } }); - - return testUtils.waitFor(async () => { - const response = await provider.query({ - request_type: 'view_state', - finality: 'final', - account_id: contract.contractId, - prefix_base64: '' - }); - expect(response).toEqual({ - block_height: expect.any(Number), - block_hash: expect.any(String), - values: [ - { key: 'bmFtZQ==', value: 'aGVsbG8=' } - ] - }); + beforeAll(async () => { + near = await testUtils.setUpTestConnection(); + provider = near.connection.provider; }); -})); -test('json rpc query view_code', withProvider(async (provider) => { - const near = await testUtils.setUpTestConnection(); - const account = await testUtils.createAccount(near); - const contract = await testUtils.deployContract(account, testUtils.generateUniqueString('test')); - - return testUtils.waitFor(async () => { - const response = await provider.query({ - request_type: 'view_code', - finality: 'final', - account_id: contract.contractId - }); - - expect(response).toEqual({ - block_height: expect.any(Number), - block_hash: expect.any(String), - code_base64: expect.any(String), - hash: expect.any(String) + test('txStatus with string hash and buffer hash', async () => { + const sender = await testUtils.createAccount(near); + const receiver = await testUtils.createAccount(near); + const outcome = await sender.sendMoney(receiver.accountId, new BN('1')); + const responseWithString = await provider.txStatus(outcome.transaction.hash, sender.accountId); + const responseWithUint8Array = await provider.txStatus(base58.decode(outcome.transaction.hash), sender.accountId); + expect(responseWithString).toMatchObject(outcome); + expect(responseWithUint8Array).toMatchObject(outcome); + }); + + test('txStatusReciept with string hash and buffer hash', async () => { + const sender = await testUtils.createAccount(near); + const receiver = await testUtils.createAccount(near); + const outcome = await sender.sendMoney(receiver.accountId, new BN('1')); + const reciepts = await provider.sendJsonRpc('EXPERIMENTAL_tx_status', [outcome.transaction.hash, sender.accountId]); + + const responseWithString = await provider.txStatusReceipts(outcome.transaction.hash, sender.accountId); + const responseWithUint8Array = await provider.txStatusReceipts(base58.decode(outcome.transaction.hash), sender.accountId); + expect('transaction_outcome' in responseWithString).toBeTruthy(); + expect('logs' in responseWithString.transaction_outcome.outcome).toBeTruthy(); + expect('receipt_ids' in responseWithString.transaction_outcome.outcome).toBeTruthy(); + expect('gas_burnt' in responseWithString.transaction_outcome.outcome).toBeTruthy(); + expect('tokens_burnt' in responseWithString.transaction_outcome.outcome).toBeTruthy(); + expect('executor_id' in responseWithString.transaction_outcome.outcome).toBeTruthy(); + expect('status' in responseWithString.transaction_outcome.outcome).toBeTruthy(); + expect(responseWithString).toMatchObject(reciepts); + expect(responseWithUint8Array).toMatchObject(reciepts); + }); + + test('json rpc query account', async () => { + const account = await testUtils.createAccount(near); + let response = await provider.query({ + request_type: 'view_account', + finality: 'optimistic', + account_id: account.accountId }); + expect(response.code_hash).toEqual('11111111111111111111111111111111'); + }); + + test('json rpc query view_state', async () => { + const account = await testUtils.createAccount(near); + const contract = await testUtils.deployContract(account, testUtils.generateUniqueString('test')); + + await contract.setValue({ args: { value: 'hello' } }); + + return testUtils.waitFor(async () => { + const response = await provider.query({ + request_type: 'view_state', + finality: 'final', + account_id: contract.contractId, + prefix_base64: '' + }); + expect(response).toEqual({ + block_height: expect.any(Number), + block_hash: expect.any(String), + proof: expect.any(Array), + values: [ + { key: 'bmFtZQ==', proof: expect.any(Array), value: 'aGVsbG8=' } + ] + }); }); }); -})); - -test('json rpc query call_function', withProvider(async (provider) => { - const near = await testUtils.setUpTestConnection(); - const account = await testUtils.createAccount(near); - const contract = await testUtils.deployContract(account, testUtils.generateUniqueString('test')); - - await contract.setValue({ args: { value: 'hello' } }); - - return testUtils.waitFor(async () => { - const response = await provider.query({ - request_type: 'call_function', - finality: 'final', - account_id: contract.contractId, - method_name: 'getValue', - args_base64: '' + + test('json rpc query view_code', async () => { + const account = await testUtils.createAccount(near); + const contract = await testUtils.deployContract(account, testUtils.generateUniqueString('test')); + + return testUtils.waitFor(async () => { + const response = await provider.query({ + request_type: 'view_code', + finality: 'final', + account_id: contract.contractId + }); + + expect(response).toEqual({ + block_height: expect.any(Number), + block_hash: expect.any(String), + code_base64: expect.any(String), + hash: expect.any(String) + }); }); - expect(response).toEqual({ - block_height: expect.any(Number), - block_hash: expect.any(String), - logs: [], - result: [ - 34, - 104, - 101, - 108, - 108, - 111, - 34 - ] + }); + + test('json rpc query call_function', async () => { + const account = await testUtils.createAccount(near); + const contract = await testUtils.deployContract(account, testUtils.generateUniqueString('test')); + + await contract.setValue({ args: { value: 'hello' } }); + + return testUtils.waitFor(async () => { + const response = await provider.query({ + request_type: 'call_function', + finality: 'final', + account_id: contract.contractId, + method_name: 'getValue', + args_base64: '' + }); + expect(response).toEqual({ + block_height: expect.any(Number), + block_hash: expect.any(String), + logs: [], + result: [ + 34, + 104, + 101, + 108, + 108, + 111, + 34 + ] + }); }); }); -})); - -test('json rpc light client proof', async () => { - const near = await testUtils.setUpTestConnection(); - const workingAccount = await testUtils.createAccount(near); - const executionOutcome = await workingAccount.sendMoney(workingAccount.accountId, new BN(10000)); - const provider = near.connection.provider; - - async function waitForStatusMatching(isMatching) { - const MAX_ATTEMPTS = 10; - for (let i = 0; i < MAX_ATTEMPTS; i++) { - await testUtils.sleep(500); - const nodeStatus = await provider.status(); - if (isMatching(nodeStatus)) { - return nodeStatus; + + test('json rpc light client proof', async () => { + const workingAccount = await testUtils.createAccount(near); + const executionOutcome = await workingAccount.sendMoney(workingAccount.accountId, new BN(10000)); + const provider = near.connection.provider; + + async function waitForStatusMatching(isMatching) { + const MAX_ATTEMPTS = 10; + for (let i = 0; i < MAX_ATTEMPTS; i++) { + await testUtils.sleep(500); + const nodeStatus = await provider.status(); + if (isMatching(nodeStatus)) { + return nodeStatus; + } } + throw new Error(`Exceeded ${MAX_ATTEMPTS} attempts waiting for matching node status.`); } - throw new Error(`Exceeded ${MAX_ATTEMPTS} attempts waiting for matching node status.`); - } - - const comittedStatus = await waitForStatusMatching(status => - status.sync_info.latest_block_hash !== executionOutcome.transaction_outcome.block_hash); - const BLOCKS_UNTIL_FINAL = 2; - const finalizedStatus = await waitForStatusMatching(status => - status.sync_info.latest_block_height > comittedStatus.sync_info.latest_block_height + BLOCKS_UNTIL_FINAL); - - const block = await provider.block({ blockId: finalizedStatus.sync_info.latest_block_hash }); - const lightClientHead = block.header.last_final_block; - let lightClientRequest = { - type: 'transaction', - light_client_head: lightClientHead, - transaction_hash: executionOutcome.transaction.hash, - sender_id: workingAccount.accountId, - }; - const lightClientProof = await provider.lightClientProof(lightClientRequest); - expect('prev_block_hash' in lightClientProof.block_header_lite).toBe(true); - expect('inner_rest_hash' in lightClientProof.block_header_lite).toBe(true); - expect('inner_lite' in lightClientProof.block_header_lite).toBe(true); - expect('timestamp_nanosec' in lightClientProof.block_header_lite.inner_lite).toBe(true); - expect(lightClientProof.outcome_proof.id).toEqual(executionOutcome.transaction_outcome.id); - expect('block_hash' in lightClientProof.outcome_proof).toBe(true); - expect(lightClientProof.outcome_root_proof).toEqual([]); - expect(lightClientProof.block_proof.length).toBeGreaterThan(0); - - // pass nonexistent hash for light client head will fail - lightClientRequest = { - type: 'transaction', - light_client_head: '11111111111111111111111111111111', - transaction_hash: executionOutcome.transaction.hash, - sender_id: workingAccount.accountId, - }; - await expect(provider.lightClientProof(lightClientRequest)).rejects.toThrow('DB Not Found Error'); - - // Use old block hash as light client head should fail - lightClientRequest = { - type: 'transaction', - light_client_head: executionOutcome.transaction_outcome.block_hash, - transaction_hash: executionOutcome.transaction.hash, - sender_id: workingAccount.accountId, - }; - - await expect(provider.lightClientProof(lightClientRequest)).rejects.toThrow(/.+ block .+ is ahead of head block .+/); + + const comittedStatus = await waitForStatusMatching(status => + status.sync_info.latest_block_hash !== executionOutcome.transaction_outcome.block_hash); + const BLOCKS_UNTIL_FINAL = 2; + const finalizedStatus = await waitForStatusMatching(status => + status.sync_info.latest_block_height > comittedStatus.sync_info.latest_block_height + BLOCKS_UNTIL_FINAL); + + const block = await provider.block({ blockId: finalizedStatus.sync_info.latest_block_hash }); + const lightClientHead = block.header.last_final_block; + let lightClientRequest = { + type: 'transaction', + light_client_head: lightClientHead, + transaction_hash: executionOutcome.transaction.hash, + sender_id: workingAccount.accountId, + }; + const lightClientProof = await provider.lightClientProof(lightClientRequest); + expect('prev_block_hash' in lightClientProof.block_header_lite).toBe(true); + expect('inner_rest_hash' in lightClientProof.block_header_lite).toBe(true); + expect('inner_lite' in lightClientProof.block_header_lite).toBe(true); + expect('timestamp_nanosec' in lightClientProof.block_header_lite.inner_lite).toBe(true); + expect(lightClientProof.outcome_proof.id).toEqual(executionOutcome.transaction_outcome.id); + expect('block_hash' in lightClientProof.outcome_proof).toBe(true); + expect(lightClientProof.outcome_root_proof).toEqual([]); + expect(lightClientProof.block_proof.length).toBeGreaterThan(0); + + // pass nonexistent hash for light client head will fail + lightClientRequest = { + type: 'transaction', + light_client_head: '11111111111111111111111111111111', + transaction_hash: executionOutcome.transaction.hash, + sender_id: workingAccount.accountId, + }; + await expect(provider.lightClientProof(lightClientRequest)).rejects.toThrow('DB Not Found Error'); + + // Use old block hash as light client head should fail + lightClientRequest = { + type: 'transaction', + light_client_head: executionOutcome.transaction_outcome.block_hash, + transaction_hash: executionOutcome.transaction.hash, + sender_id: workingAccount.accountId, + }; + + await expect(provider.lightClientProof(lightClientRequest)).rejects.toThrow(/.+ block .+ is ahead of head block .+/); + }); }); diff --git a/packages/accounts/test/test-utils.js b/packages/accounts/test/test-utils.js index 14bbf577d4..086d7706a1 100644 --- a/packages/accounts/test/test-utils.js +++ b/packages/accounts/test/test-utils.js @@ -51,14 +51,15 @@ async function loadGuestBookContractCode() { } async function setUpTestConnection() { const keyStore = new InMemoryKeyStore(); - const config = Object.assign(require('./config')(process.env.NODE_ENV || 'test'), { + const config = Object.assign(await require('./config')(process.env.NODE_ENV || 'test'), { networkId, keyStore }); if (config.masterAccount) { // full accessKey on ci-testnet, dedicated rpc for tests. - await keyStore.setKey(networkId, config.masterAccount, KeyPair.fromString('ed25519:2wyRcSwSuHtRVmkMCGjPwnzZmQLeXLzLLyED1NDMt4BjnKgQL6tF85yBx6Jr26D2dUNeC716RBoTxntVHsegogYw')); + const secretKey = config.secretKey || 'ed25519:2wyRcSwSuHtRVmkMCGjPwnzZmQLeXLzLLyED1NDMt4BjnKgQL6tF85yBx6Jr26D2dUNeC716RBoTxntVHsegogYw'; + await keyStore.setKey(networkId, config.masterAccount, KeyPair.fromString(secretKey)); } const connection = Connection.fromConfig({ diff --git a/packages/biometric-ed25519/src/index.ts b/packages/biometric-ed25519/src/index.ts index 5dbd96acac..57b31af01e 100644 --- a/packages/biometric-ed25519/src/index.ts +++ b/packages/biometric-ed25519/src/index.ts @@ -106,8 +106,8 @@ export const getKeys = async (username: string): Promise<[KeyPair, KeyPair]> => Buffer.from(new Uint8Array(base64.toArrayBuffer(getAssertionResponse.response.clientDataJSON, true))) ); const clientDataJSONHash = await clientDataSha256.digest(); - const AuthenticatiorDataJSONHash = Buffer.from(new Uint8Array(base64.toArrayBuffer(getAssertionResponse.response.authenticatorData, true))); - const authenticatorAndClientDataJSONHash = Buffer.concat([AuthenticatiorDataJSONHash, clientDataJSONHash]); + const authenticatorDataJSONHash = Buffer.from(new Uint8Array(base64.toArrayBuffer(getAssertionResponse.response.authenticatorData, true))); + const authenticatorAndClientDataJSONHash = Buffer.concat([authenticatorDataJSONHash, clientDataJSONHash]); const correctPKs = await recoverPublicKey(rAndS.children[0].value, rAndS.children[1].value, authenticatorAndClientDataJSONHash, 0); diff --git a/packages/crypto/src/key_pair.ts b/packages/crypto/src/key_pair.ts index d02790a156..fb5d5ca59f 100644 --- a/packages/crypto/src/key_pair.ts +++ b/packages/crypto/src/key_pair.ts @@ -13,6 +13,11 @@ export abstract class KeyPair extends KeyPairBase { } } + /** + * Creates a key pair from an encoded key string. + * @param encodedKey The encoded key string. + * @returns {KeyPair} The key pair created from the encoded key string. + */ static fromString(encodedKey: string): KeyPair { const parts = encodedKey.split(':'); if (parts.length === 1) { diff --git a/packages/crypto/src/key_pair_ed25519.ts b/packages/crypto/src/key_pair_ed25519.ts index 3047cfc4fd..6462c87692 100644 --- a/packages/crypto/src/key_pair_ed25519.ts +++ b/packages/crypto/src/key_pair_ed25519.ts @@ -18,7 +18,7 @@ export class KeyPairEd25519 extends KeyPairBase { /** * Construct an instance of key pair given a secret key. * It's generally assumed that these are encoded in base58. - * @param {string} extendedSecretKey + * @param extendedSecretKey */ constructor(extendedSecretKey: string) { super(); @@ -47,19 +47,38 @@ export class KeyPairEd25519 extends KeyPairBase { return new KeyPairEd25519(baseEncode(extendedSecretKey)); } + /** + * Signs a message using the key pair's secret key. + * @param message The message to be signed. + * @returns {Signature} The signature object containing the signature and the public key. + */ sign(message: Uint8Array): Signature { const signature = ed25519.sign(message, baseDecode(this.secretKey)); return { signature, publicKey: this.publicKey }; } + /** + * Verifies the signature of a message using the key pair's public key. + * @param message The message to be verified. + * @param signature The signature to be verified. + * @returns {boolean} `true` if the signature is valid, otherwise `false`. + */ verify(message: Uint8Array, signature: Uint8Array): boolean { return this.publicKey.verify(message, signature); } + /** + * Returns a string representation of the key pair in the format 'ed25519:[extendedSecretKey]'. + * @returns {string} The string representation of the key pair. + */ toString(): string { return `ed25519:${this.extendedSecretKey}`; } + /** + * Retrieves the public key associated with the key pair. + * @returns {PublicKey} The public key. + */ getPublicKey(): PublicKey { return this.publicKey; } diff --git a/packages/crypto/src/public_key.ts b/packages/crypto/src/public_key.ts index 0959cd4d6e..8b06dd8663 100644 --- a/packages/crypto/src/public_key.ts +++ b/packages/crypto/src/public_key.ts @@ -25,6 +25,11 @@ export class PublicKey extends Assignable { keyType: KeyType; data: Uint8Array; + /** + * Creates a PublicKey instance from a string or an existing PublicKey instance. + * @param value The string or PublicKey instance to create a PublicKey from. + * @returns {PublicKey} The PublicKey instance. + */ static from(value: string | PublicKey): PublicKey { if (typeof value === 'string') { return PublicKey.fromString(value); @@ -32,6 +37,11 @@ export class PublicKey extends Assignable { return value; } + /** + * Creates a PublicKey instance from an encoded key string. + * @param encodedKey The encoded key string. + * @returns {PublicKey} The PublicKey instance created from the encoded key string. + */ static fromString(encodedKey: string): PublicKey { const parts = encodedKey.split(':'); let publicKey: string; @@ -51,10 +61,20 @@ export class PublicKey extends Assignable { return new PublicKey({ keyType, data: decodedPublicKey }); } + /** + * Returns a string representation of the public key. + * @returns {string} The string representation of the public key. + */ toString(): string { return `${key_type_to_str(this.keyType)}:${baseEncode(this.data)}`; } + /** + * Verifies a message signature using the public key. + * @param message The message to be verified. + * @param signature The signature to be verified. + * @returns {boolean} `true` if the signature is valid, otherwise `false`. + */ verify(message: Uint8Array, signature: Uint8Array): boolean { switch (this.keyType) { case KeyType.ED25519: return ed25519.verify(signature, message, this.data); diff --git a/packages/iframe-rpc/src/iframe-rpc.ts b/packages/iframe-rpc/src/iframe-rpc.ts index 5d466b93cd..e97bfcfcd3 100644 --- a/packages/iframe-rpc/src/iframe-rpc.ts +++ b/packages/iframe-rpc/src/iframe-rpc.ts @@ -35,6 +35,10 @@ export class IFrameRPC extends EventEmitter { private remoteProtocolVersion: string | undefined; private readonly removeMessageListener: () => void; + /** + * Creates an instance of IFrameRPC. + * @param options The configuration options for IFrameRPC. + */ constructor(private readonly options: IRPCOptions) { super(); this.removeMessageListener = (options.receiver || windowReceiver).readMessages(this.messageEventListener); @@ -57,11 +61,22 @@ export class IFrameRPC extends EventEmitter { }); } + /** + * Static method to get a ready instance of IFrameRPC based on the provided options. + * @param options The configuration options for IFrameRPC. + * @returns A Promise that resolves to the ready IFrameRPC instance. + */ static getReadyInstance(options: IRPCOptions): Promise { const rpc = new IFrameRPC(options); return rpc.isReady.then(() => rpc); } + /** + * Binds a method handler for the specified RPC method. + * @param method The RPC method name. + * @param handler The method handler function. + * @returns The current IFrameRPC instance. + */ public bindMethodHandler(method: string, handler: (params: T) => Promise | any): this { this.on(method, (data: IRPCMethod) => { new Promise(resolve => resolve(handler(data.params))) @@ -89,6 +104,12 @@ export class IFrameRPC extends EventEmitter { return this; } + /** + * Calls an RPC method with the specified method name and parameters. + * @param method The RPC method name. + * @param params The parameters for the RPC method. + * @returns A Promise that resolves with the result of the RPC method. + */ public callMethod(method: string, params: object): Promise { const id = method === 'ready' ? readyId : this.lastCallId; const message: IRPCMethod = { @@ -113,11 +134,18 @@ export class IFrameRPC extends EventEmitter { }); } + /** + * Destroys the IFrameRPC instance, removing event listeners. + */ public destroy() { this.emit('destroy'); this.removeMessageListener(); } + /** + * Retrieves the remote protocol version. + * @returns The remote protocol version. + */ public remoteVersion(): string | undefined { return this.remoteProtocolVersion; } diff --git a/packages/keystores-browser/src/browser_local_storage_key_store.ts b/packages/keystores-browser/src/browser_local_storage_key_store.ts index 9472b183b3..e72e6cf6ed 100644 --- a/packages/keystores-browser/src/browser_local_storage_key_store.ts +++ b/packages/keystores-browser/src/browser_local_storage_key_store.ts @@ -121,7 +121,7 @@ export class BrowserLocalStorageKeyStore extends KeyStore { * @hidden * Helper function to retrieve a local storage key * @param networkId The targeted network. (ex. default, betanet, etc…) - * @param accountId The NEAR account tied to the storage keythat's sought + * @param accountId The NEAR account tied to the storage key that's sought * @returns {string} An example might be: `near-api-js:keystore:near-friend:default` */ private storageKeyForSecretKey(networkId: string, accountId: string): string { diff --git a/packages/keystores/src/merge_key_store.ts b/packages/keystores/src/merge_key_store.ts index 2fc6227dc6..4caf4b20f2 100644 --- a/packages/keystores/src/merge_key_store.ts +++ b/packages/keystores/src/merge_key_store.ts @@ -45,6 +45,7 @@ export class MergeKeyStore extends KeyStore { /** * @param keyStores read calls are attempted from start to end of array + * @param options KeyStore options * @param options.writeKeyStoreIndex the keystore index that will receive all write calls */ constructor(keyStores: KeyStore[], options: MergeKeyStoreOptions = { writeKeyStoreIndex: 0 }) { diff --git a/packages/near-api-js/package.json b/packages/near-api-js/package.json index efb1f59cfe..4ff3cdafdd 100644 --- a/packages/near-api-js/package.json +++ b/packages/near-api-js/package.json @@ -49,7 +49,8 @@ "rimraf": "3.0.2", "semver": "7.1.1", "ts-jest": "26.5.6", - "uglifyify": "5.0.1" + "uglifyify": "5.0.1", + "near-workspaces": "3.4.0" }, "keywords": [], "license": "(MIT AND Apache-2.0)", diff --git a/packages/near-api-js/src/connect.ts b/packages/near-api-js/src/connect.ts index 64777da84e..dada230405 100644 --- a/packages/near-api-js/src/connect.ts +++ b/packages/near-api-js/src/connect.ts @@ -45,6 +45,26 @@ export interface ConnectConfig extends NearConfig { /** * Initialize connection to Near network. + * @param config The configuration object for connecting to NEAR Protocol. + * @returns A Promise that resolves to a `Near` object representing the connection. + * + * @example + * ```js + * const connectionConfig = { + * networkId: 'testnet', + * nodeUrl: 'https://rpc.testnet.near.org', + * walletUrl: 'https://wallet.testnet.near.org', + * helperUrl: 'https://helper.testnet.near.org', + * keyStore: new InMemoryKeyStore(), + * deps: { keyStore: new BrowserLocalStorageKeyStore() }, + * logger: true, + * keyPath: '/path/to/account-key.json', + * masterAccount: 'master-account.near', + * }; + * + * const nearConnection = await connect(connectionConfig); + * console.log(nearConnection); // Near object representing the connection + * ``` */ export async function connect(config: ConnectConfig): Promise { if (config.logger === false) { diff --git a/packages/near-api-js/test/config.js b/packages/near-api-js/test/config.js index 4af00c1c65..7bbf1bfc0c 100644 --- a/packages/near-api-js/test/config.js +++ b/packages/near-api-js/test/config.js @@ -1,4 +1,7 @@ -module.exports = function getConfig(env) { +const { Worker } = require('near-workspaces'); +const fs = require('fs'); +let worker; +module.exports = async function getConfig(env) { switch (env) { case 'production': case 'mainnet': @@ -33,10 +36,14 @@ module.exports = function getConfig(env) { }; case 'test': case 'ci': + if (!worker) worker = await Worker.init(); + const keyFile = fs.readFileSync(`${worker.rootAccount.manager.config.homeDir}/validator_key.json`); + const keyPair = JSON.parse(keyFile.toString()); return { - networkId: 'shared-test', - nodeUrl: 'https://rpc.ci-testnet.near.org', - masterAccount: 'test.near', + networkId: worker.config.network, + nodeUrl: worker.manager.config.rpcAddr, + masterAccount: worker.rootAccount._accountId, + secretKey: keyPair.secret_key || keyPair.private_key }; default: throw Error(`Unconfigured environment '${env}'. Can be configured in src/config.js.`); diff --git a/packages/near-api-js/test/test-utils.js b/packages/near-api-js/test/test-utils.js index 5ff2ebbe9a..e70ec851ff 100644 --- a/packages/near-api-js/test/test-utils.js +++ b/packages/near-api-js/test/test-utils.js @@ -18,14 +18,15 @@ const RANDOM_ACCOUNT_LENGTH = 40; async function setUpTestConnection() { const keyStore = new nearApi.keyStores.InMemoryKeyStore(); - const config = Object.assign(require('./config')(process.env.NODE_ENV || 'test'), { - networkId: networkId, + const config = Object.assign(await require('./config')(process.env.NODE_ENV || 'test'), { + networkId, keyStore }); if (config.masterAccount) { // full accessKey on ci-testnet, dedicated rpc for tests. - await keyStore.setKey(networkId, config.masterAccount, nearApi.utils.KeyPair.fromString('ed25519:2wyRcSwSuHtRVmkMCGjPwnzZmQLeXLzLLyED1NDMt4BjnKgQL6tF85yBx6Jr26D2dUNeC716RBoTxntVHsegogYw')); + const secretKey = config.secretKey || 'ed25519:2wyRcSwSuHtRVmkMCGjPwnzZmQLeXLzLLyED1NDMt4BjnKgQL6tF85yBx6Jr26D2dUNeC716RBoTxntVHsegogYw'; + await keyStore.setKey(networkId, config.masterAccount, KeyPair.fromString(secretKey)); } return nearApi.connect(config); } diff --git a/packages/providers/package.json b/packages/providers/package.json index 40122c4753..00a5166451 100644 --- a/packages/providers/package.json +++ b/packages/providers/package.json @@ -26,6 +26,7 @@ "devDependencies": { "@types/node": "18.11.18", "jest": "26.0.1", + "near-workspaces": "3.4.0", "ts-jest": "26.5.6", "typescript": "4.9.4" }, diff --git a/packages/providers/src/fetch_json.ts b/packages/providers/src/fetch_json.ts index 1e8836f1eb..376767eeab 100644 --- a/packages/providers/src/fetch_json.ts +++ b/packages/providers/src/fetch_json.ts @@ -17,6 +17,12 @@ export interface ConnectionInfo { headers?: { [key: string]: string | number }; } +/** + * Performs an HTTP request to a specified URL or connection and returns the parsed JSON response. + * @param connectionInfoOrUrl The connection information or URL for the HTTP request. + * @param json The JSON payload to be included in the request body for POST requests. + * @returns A Promise that resolves to the parsed JSON response from the HTTP request. + */ export async function fetchJson(connectionInfoOrUrl: string | ConnectionInfo, json?: string): Promise { let connectionInfo: ConnectionInfo = { url: null }; if (typeof (connectionInfoOrUrl) === 'string') { diff --git a/packages/providers/test/providers.test.js b/packages/providers/test/providers.test.js index c06c776edc..509860b9e3 100644 --- a/packages/providers/test/providers.test.js +++ b/packages/providers/test/providers.test.js @@ -1,154 +1,177 @@ const { getTransactionLastResult } = require('@near-js/utils'); - +const { Worker } = require('near-workspaces'); const { JsonRpcProvider } = require('../lib'); jest.setTimeout(20000); -const withProvider = (fn) => { - return () => fn(new JsonRpcProvider({ url: 'https://rpc.ci-testnet.near.org' })); -}; - -test('json rpc fetch node status', withProvider(async (provider) => { - let response = await provider.status(); - expect(response.chain_id).toBeTruthy(); -})); - -test('json rpc fetch block info', withProvider(async (provider) => { - let stat = await provider.status(); - let height = stat.sync_info.latest_block_height - 1; - let response = await provider.block({ blockId: height }); - expect(response.header.height).toEqual(height); - - let sameBlock = await provider.block({ blockId: response.header.hash }); - expect(sameBlock.header.height).toEqual(height); - - let optimisticBlock = await provider.block({ finality: 'optimistic' }); - expect(optimisticBlock.header.height - height).toBeLessThan(5); +describe('providers', () => { + let worker; + let provider; - let nearFinalBlock = await provider.block({ finality: 'near-final' }); - expect(nearFinalBlock.header.height - height).toBeLessThan(5); - - let finalBlock = await provider.block({ finality: 'final' }); - expect(finalBlock.header.height - height).toBeLessThan(5); -})); - -test('json rpc fetch block changes', withProvider(async (provider) => { - let stat = await provider.status(); - let height = stat.sync_info.latest_block_height - 1; - let response = await provider.blockChanges({ blockId: height }); - - expect(response).toMatchObject({ - block_hash: expect.any(String), - changes: expect.any(Array) + beforeAll(async () => { + worker = await Worker.init(); + provider = new JsonRpcProvider({ url: worker.manager.config.rpcAddr }); + await new Promise(resolve => setTimeout(resolve, 2000)); }); -})); - -test('json rpc fetch chunk info', withProvider(async (provider) => { - let stat = await provider.status(); - let height = stat.sync_info.latest_block_height - 1; - let response = await provider.chunk([height, 0]); - expect(response.header.shard_id).toEqual(0); - let sameChunk = await provider.chunk(response.header.chunk_hash); - expect(sameChunk.header.chunk_hash).toEqual(response.header.chunk_hash); - expect(sameChunk.header.shard_id).toEqual(0); -})); - -test('json rpc fetch validators info', withProvider(async (provider) => { - let validators = await provider.validators(null); - expect(validators.current_validators.length).toBeGreaterThanOrEqual(1); -})); -test('json rpc query with block_id', withProvider(async (provider) => { - const stat = await provider.status(); - let block_id = stat.sync_info.latest_block_height - 1; - - const response = await provider.query({ - block_id, - request_type: 'view_account', - account_id: 'test.near' + afterAll(async () => { + await worker.tearDown(); }); - expect(response).toEqual({ - block_height: expect.any(Number), - block_hash: expect.any(String), - amount: expect.any(String), - locked: expect.any(String), - code_hash: '11111111111111111111111111111111', - storage_usage: 182, - storage_paid_at: 0, + test('json rpc fetch node status', async () => { + let response = await provider.status(); + expect(response.chain_id).toBeTruthy(); }); -})); - -test('json rpc query view_account', withProvider(async (provider) => { - const response = await provider.query({ - request_type: 'view_account', - finality: 'final', - account_id: 'test.near' + + test('json rpc fetch block info', async () => { + let stat = await provider.status(); + let height = stat.sync_info.latest_block_height - 1; + let response = await provider.block({ blockId: height }); + expect(response.header.height).toEqual(height); + + let sameBlock = await provider.block({ blockId: response.header.hash }); + expect(sameBlock.header.height).toEqual(height); + + let optimisticBlock = await provider.block({ finality: 'optimistic' }); + expect(optimisticBlock.header.height - height).toBeLessThan(5); + + let nearFinalBlock = await provider.block({ finality: 'near-final' }); + expect(nearFinalBlock.header.height - height).toBeLessThan(5); + + let finalBlock = await provider.block({ finality: 'final' }); + expect(finalBlock.header.height - height).toBeLessThan(5); }); - - expect(response).toEqual({ - block_height: expect.any(Number), - block_hash: expect.any(String), - amount: expect.any(String), - locked: expect.any(String), - code_hash: '11111111111111111111111111111111', - storage_usage: 182, - storage_paid_at: 0, + + test('json rpc fetch block changes', async () => { + let stat = await provider.status(); + let height = stat.sync_info.latest_block_height - 1; + let response = await provider.blockChanges({ blockId: height }); + + expect(response).toMatchObject({ + block_hash: expect.any(String), + changes: expect.any(Array) + }); + }); + + test('json rpc fetch chunk info', async () => { + let stat = await provider.status(); + let height = stat.sync_info.latest_block_height - 1; + let response = await provider.chunk([height, 0]); + expect(response.header.shard_id).toEqual(0); + let sameChunk = await provider.chunk(response.header.chunk_hash); + expect(sameChunk.header.chunk_hash).toEqual(response.header.chunk_hash); + expect(sameChunk.header.shard_id).toEqual(0); + }); + + test('json rpc fetch validators info', async () => { + let validators = await provider.validators(null); + expect(validators.current_validators.length).toBeGreaterThanOrEqual(1); + }); + + test('json rpc query with block_id', async () => { + const stat = await provider.status(); + let block_id = stat.sync_info.latest_block_height - 1; + + const response = await provider.query({ + block_id, + request_type: 'view_account', + account_id: 'test.near' + }); + + expect(response).toEqual({ + block_height: expect.any(Number), + block_hash: expect.any(String), + amount: expect.any(String), + locked: expect.any(String), + code_hash: '11111111111111111111111111111111', + storage_usage: 182, + storage_paid_at: 0, + }); + }); + + test('json rpc query view_account', async () => { + const response = await provider.query({ + request_type: 'view_account', + finality: 'final', + account_id: 'test.near' + }); + + expect(response).toEqual({ + block_height: expect.any(Number), + block_hash: expect.any(String), + amount: expect.any(String), + locked: expect.any(String), + code_hash: '11111111111111111111111111111111', + storage_usage: 182, + storage_paid_at: 0, + }); + }); + + test('final tx result', async () => { + const result = { + status: { SuccessValue: 'e30=' }, + transaction: { id: '11111', outcome: { status: { SuccessReceiptId: '11112' }, logs: [], receipt_ids: ['11112'], gas_burnt: 1 } }, + receipts: [ + { id: '11112', outcome: { status: { SuccessValue: 'e30=' }, logs: [], receipt_ids: ['11112'], gas_burnt: 9001 } }, + { id: '11113', outcome: { status: { SuccessValue: '' }, logs: [], receipt_ids: [], gas_burnt: 0 } } + ] + }; + expect(getTransactionLastResult(result)).toEqual({}); + }); + + test('final tx result with null', async () => { + const result = { + status: 'Failure', + transaction: { id: '11111', outcome: { status: { SuccessReceiptId: '11112' }, logs: [], receipt_ids: ['11112'], gas_burnt: 1 } }, + receipts: [ + { id: '11112', outcome: { status: 'Failure', logs: [], receipt_ids: ['11112'], gas_burnt: 9001 } }, + { id: '11113', outcome: { status: { SuccessValue: '' }, logs: [], receipt_ids: [], gas_burnt: 0 } } + ] + }; + expect(getTransactionLastResult(result)).toEqual(null); + }); + + test('json rpc fetch protocol config', async () => { + const status = await provider.status(); + const blockHeight = status.sync_info.latest_block_height; + const blockHash = status.sync_info.latest_block_hash; + for (const blockReference of [{ sync_checkpoint: 'genesis' }, { blockId: blockHeight }, { blockId: blockHash }, { finality: 'final' }, { finality: 'optimistic' }]) { + const response = await provider.experimental_protocolConfig(blockReference); + expect('chain_id' in response).toBe(true); + expect('genesis_height' in response).toBe(true); + expect('runtime_config' in response).toBe(true); + expect('storage_amount_per_byte' in response.runtime_config).toBe(true); + } + }); + + test('json rpc gas price', async () => { + let status = await provider.status(); + let positiveIntegerRegex = /^[+]?\d+([.]\d+)?$/; + + let response1 = await provider.gasPrice(status.sync_info.latest_block_height); + expect(response1.gas_price).toMatch(positiveIntegerRegex); + + let response2 = await provider.gasPrice(status.sync_info.latest_block_hash); + expect(response2.gas_price).toMatch(positiveIntegerRegex); + + let response3 = await provider.gasPrice(); + expect(response3.gas_price).toMatch(positiveIntegerRegex); + }); + + test('JsonRpc connection object exist without connectionInfo provided', async () => { + const provider = new JsonRpcProvider(); + expect(provider.connection).toStrictEqual({ url: '' }); + }); + + test('near json rpc fetch node status', async () => { + let response = await provider.status(); + expect(response.chain_id).toBeTruthy(); }); -})); - -test('final tx result', async () => { - const result = { - status: { SuccessValue: 'e30=' }, - transaction: { id: '11111', outcome: { status: { SuccessReceiptId: '11112' }, logs: [], receipt_ids: ['11112'], gas_burnt: 1 } }, - receipts: [ - { id: '11112', outcome: { status: { SuccessValue: 'e30=' }, logs: [], receipt_ids: ['11112'], gas_burnt: 9001 } }, - { id: '11113', outcome: { status: { SuccessValue: '' }, logs: [], receipt_ids: [], gas_burnt: 0 } } - ] - }; - expect(getTransactionLastResult(result)).toEqual({}); -}); - -test('final tx result with null', async () => { - const result = { - status: 'Failure', - transaction: { id: '11111', outcome: { status: { SuccessReceiptId: '11112' }, logs: [], receipt_ids: ['11112'], gas_burnt: 1 } }, - receipts: [ - { id: '11112', outcome: { status: 'Failure', logs: [], receipt_ids: ['11112'], gas_burnt: 9001 } }, - { id: '11113', outcome: { status: { SuccessValue: '' }, logs: [], receipt_ids: [], gas_burnt: 0 } } - ] - }; - expect(getTransactionLastResult(result)).toEqual(null); }); -test('json rpc fetch protocol config', withProvider(async (provider) => { - const status = await provider.status(); - const blockHeight = status.sync_info.latest_block_height; - const blockHash = status.sync_info.latest_block_hash; - for (const blockReference of [{ sync_checkpoint: 'genesis' }, { blockId: blockHeight }, { blockId: blockHash }, { finality: 'final' }, { finality: 'optimistic' }]) { - const response = await provider.experimental_protocolConfig(blockReference); - expect('chain_id' in response).toBe(true); - expect('genesis_height' in response).toBe(true); - expect('runtime_config' in response).toBe(true); - expect('storage_amount_per_byte' in response.runtime_config).toBe(true); - } -})); - -test('json rpc gas price', withProvider(async (provider) => { - let status = await provider.status(); - let positiveIntegerRegex = /^[+]?\d+([.]\d+)?$/; - - let response1 = await provider.gasPrice(status.sync_info.latest_block_height); - expect(response1.gas_price).toMatch(positiveIntegerRegex); - - let response2 = await provider.gasPrice(status.sync_info.latest_block_hash); - expect(response2.gas_price).toMatch(positiveIntegerRegex); - - let response3 = await provider.gasPrice(); - expect(response3.gas_price).toMatch(positiveIntegerRegex); -})); - -test('json rpc get next light client block', withProvider(async (provider) => { +// TODO: Use a near-workspaces Worker when time traveling is available +test('json rpc get next light client block', async () => { + const provider = new JsonRpcProvider({ url: 'https://rpc.ci-testnet.near.org' }); const stat = await provider.status(); // Get block in at least the last epoch (epoch duration 43,200 blocks on mainnet and testnet) @@ -175,15 +198,4 @@ test('json rpc get next light client block', withProvider(async (provider) => { expect('next_block_inner_hash' in nextBlock).toBeTruthy(); expect('inner_rest_hash' in nextBlock).toBeTruthy(); expect('approvals_after_next' in nextBlock).toBeTruthy(); -})); - -test('JsonRpc connection object exist without connectionInfo provided', async () => { - const provider = new JsonRpcProvider(); - expect(provider.connection).toStrictEqual({ url: '' }); -}); - -test('near json rpc fetch node status', async () => { - const provider = new JsonRpcProvider({ url: 'https://rpc.ci-testnet.near.org' }); - let response = await provider.status(); - expect(response.chain_id).toBeTruthy(); -}); +}); \ No newline at end of file diff --git a/packages/signers/README.md b/packages/signers/README.md index ca54f591d1..a23ed8dc4c 100644 --- a/packages/signers/README.md +++ b/packages/signers/README.md @@ -4,8 +4,8 @@ A collection of classes and types to facilitate cryptographic signing. ## Modules -- [Signer](https://github.com/near/near-api-js/blob/master/packages/signer/src/ssigner.ts) abstract class for cryptographic signing -- [InMemorySigner](https://github.com/near/near-api-js/blob/master/packages/signer/src/in_memory_signer.ts) implementation of `Signer` using [InMemoryKeyStore](https://github.com/near/near-api-js/blob/master/packages/keystores/src/in_memory_key_store.ts) to provide keys +- [Signer](https://github.com/near/near-api-js/blob/master/packages/signers/src/signer.ts) abstract class for cryptographic signing +- [InMemorySigner](https://github.com/near/near-api-js/blob/master/packages/signers/src/in_memory_signer.ts) implementation of `Signer` using [InMemoryKeyStore](https://github.com/near/near-api-js/blob/master/packages/keystores/src/in_memory_key_store.ts) to provide keys # License diff --git a/packages/signers/src/in_memory_signer.ts b/packages/signers/src/in_memory_signer.ts index 5c0797b5bf..273b79d4f7 100644 --- a/packages/signers/src/in_memory_signer.ts +++ b/packages/signers/src/in_memory_signer.ts @@ -1,5 +1,5 @@ import { KeyPair, PublicKey, Signature } from '@near-js/crypto'; -import { InMemoryKeyStore, KeyStore } from '@near-js/keystores' +import { InMemoryKeyStore, KeyStore } from '@near-js/keystores'; import { sha256 } from '@noble/hashes/sha256'; import { Signer } from './signer'; diff --git a/packages/signers/src/signer.ts b/packages/signers/src/signer.ts index d5d5ae670e..97ec749ffa 100644 --- a/packages/signers/src/signer.ts +++ b/packages/signers/src/signer.ts @@ -7,6 +7,8 @@ export abstract class Signer { /** * Creates new key and returns public key. + * @param accountId accountId to retrieve from. + * @param networkId The targeted network. (ex. default, betanet, etc…) */ abstract createKey(accountId: string, networkId?: string): Promise; diff --git a/packages/transactions/src/action_creators.ts b/packages/transactions/src/action_creators.ts index 6f5ee1f36a..021106b97b 100644 --- a/packages/transactions/src/action_creators.ts +++ b/packages/transactions/src/action_creators.ts @@ -20,6 +20,10 @@ import { import { DelegateAction } from './delegate'; import { Signature } from './signature'; +/** + * Creates a full access key with full access permissions. + * @returns A new full access key. + */ function fullAccessKey(): AccessKey { return new AccessKey({ nonce: 0, @@ -28,7 +32,13 @@ function fullAccessKey(): AccessKey { }) }); } - +/** + * Creates an access key with function call permission for a specific receiver and method names. + * @param receiverId The NEAR account ID of the function call receiver. + * @param methodNames An array of method names allowed for function calls. + * @param allowance An optional allowance (maximum amount) for the function call. Default: Unlimited. + * @returns A new access key with function call permission. + */ function functionCallAccessKey(receiverId: string, methodNames: string[], allowance?: BN): AccessKey { return new AccessKey({ nonce: 0, @@ -38,14 +48,28 @@ function functionCallAccessKey(receiverId: string, methodNames: string[], allowa }); } +/** + * Creates a new action for creating a new NEAR account. + * @returns A new action for creating a new account. + */ function createAccount(): Action { return new Action({ createAccount: new CreateAccount({}) }); } +/** + * Creates a new action for deploying a contract with the provided code. + * @param code The Uint8Array representing the code of the contract. + * @returns A new action for deploying a contract. + */ function deployContract(code: Uint8Array): Action { return new Action({ deployContract: new DeployContract({ code }) }); } +/** + * Converts an input argument to a Buffer, handling cases for both JSON and Uint8Array. + * @param args The input argument, either JSON object or Uint8Array. + * @returns A Buffer representation of the input argument. + */ export function stringifyJsonOrBytes(args: any): Buffer { const isUint8Array = args.byteLength !== undefined && args.byteLength === args.length; return isUint8Array ? args : Buffer.from(JSON.stringify(args)); @@ -77,26 +101,59 @@ function functionCall(methodName: string, args: Uint8Array | object, gas: BN = n }); } +/** + * Creates a new action for transferring funds, optionally specifying a deposit amount. + * @param deposit The amount to be deposited along with the transfer. Default: 0. + * @returns A new action for transferring funds. + */ function transfer(deposit: BN = new BN(0)): Action { return new Action({ transfer: new Transfer({ deposit }) }); } +/** + * Creates a new action for staking tokens, specifying the stake amount and public key. + * @param stake The amount to be staked. Default: 0. + * @param publicKey The public key associated with the staking action. + * @returns A new action for staking tokens. + */ function stake(stake: BN = new BN(0), publicKey: PublicKey): Action { return new Action({ stake: new Stake({ stake, publicKey }) }); } +/** + * Creates a new action for adding a public key with a specified access key. + * @param publicKey The public key to be added. + * @param accessKey The access key associated with the added public key. + * @returns A new action for adding a public key. + */ function addKey(publicKey: PublicKey, accessKey: AccessKey): Action { return new Action({ addKey: new AddKey({ publicKey, accessKey }) }); } +/** + * Creates a new action for deleting a public key. + * @param publicKey The public key to be deleted. + * @returns A new action for deleting a public key. + */ function deleteKey(publicKey: PublicKey): Action { return new Action({ deleteKey: new DeleteKey({ publicKey }) }); } +/** + * Creates a new action for deleting an account with the specified beneficiary ID. + * @param beneficiaryId The NEAR account ID of the beneficiary. + * @returns A new action for deleting an account. + */ function deleteAccount(beneficiaryId: string): Action { return new Action({ deleteAccount: new DeleteAccount({ beneficiaryId }) }); } +/** + * Creates a new action for a signed delegation, specifying the delegate action and signature. + * @param delegateAction The delegate action to be performed. + * @param signature The signature associated with the delegate action. + * @returns A new action for a signed delegation. + */ function signedDelegate({ delegateAction, signature }: { delegateAction: DelegateAction, signature: Signature }): Action { return new Action({ signedDelegate: new SignedDelegate({ delegateAction, signature }) }); } diff --git a/packages/transactions/src/create_transaction.ts b/packages/transactions/src/create_transaction.ts index 5d5d1198af..5da87aa248 100644 --- a/packages/transactions/src/create_transaction.ts +++ b/packages/transactions/src/create_transaction.ts @@ -4,6 +4,16 @@ import BN from 'bn.js'; import { Action } from './actions'; import { Transaction } from './schema'; +/** + * Creates a new transaction object with the provided parameters. + * @param signerId The NEAR account ID of the transaction signer. + * @param publicKey The public key associated with the signer. + * @param receiverId The NEAR account ID of the transaction receiver. + * @param nonce The nonce value for the transaction, represented as a BN, string, or number. + * @param actions An array of transaction actions to be performed. + * @param blockHash The hash of the block where the transaction will be included. + * @returns A new transaction object initialized with the provided parameters. + */ export function createTransaction(signerId: string, publicKey: PublicKey, receiverId: string, nonce: BN | string | number, actions: Action[], blockHash: Uint8Array): Transaction { return new Transaction({ signerId, publicKey, nonce: new BN(nonce), receiverId, actions, blockHash }); } diff --git a/packages/transactions/src/delegate.ts b/packages/transactions/src/delegate.ts index de6768f841..c25db66427 100644 --- a/packages/transactions/src/delegate.ts +++ b/packages/transactions/src/delegate.ts @@ -27,12 +27,12 @@ export class DelegateAction extends Assignable { /** * Compose a delegate action for inclusion with a meta transaction signed on the sender's behalf - * @params.actions The set of actions to be included in the meta transaction - * @params.maxBlockHeight The maximum block height for which this action can be executed as part of a transaction - * @params.nonce Current nonce on the access key used to sign the delegate action - * @params.publicKey Public key for the access key used to sign the delegate action - * @params.receiverId Account ID for the intended receiver of the meta transaction - * @params.senderId Account ID for the intended signer of the delegate action + * @param actions The set of actions to be included in the meta transaction + * @param maxBlockHeight The maximum block height for which this action can be executed as part of a transaction + * @param nonce Current nonce on the access key used to sign the delegate action + * @param publicKey Public key for the access key used to sign the delegate action + * @param receiverId Account ID for the intended receiver of the meta transaction + * @param senderId Account ID for the intended signer of the delegate action */ export function buildDelegateAction({ actions, diff --git a/packages/transactions/src/schema.ts b/packages/transactions/src/schema.ts index 39690ae92b..4f909a685f 100644 --- a/packages/transactions/src/schema.ts +++ b/packages/transactions/src/schema.ts @@ -32,6 +32,11 @@ export function encodeSignedDelegate(signedDelegate: SignedDelegate) { return serialize(SCHEMA.SignedDelegate, signedDelegate); } +/** +* Borsh-encode a transaction or signed transaction into a serialized form. +* @param transaction The transaction or signed transaction object to be encoded. +* @returns A serialized representation of the input transaction. +*/ export function encodeTransaction(transaction: Transaction | SignedTransaction) { const schema: Schema = transaction instanceof SignedTransaction ? SCHEMA.SignedTransaction : SCHEMA.Transaction; return serialize(schema, transaction); diff --git a/packages/transactions/src/sign.ts b/packages/transactions/src/sign.ts index 0c2cc4422b..f84fc5a844 100644 --- a/packages/transactions/src/sign.ts +++ b/packages/transactions/src/sign.ts @@ -56,8 +56,9 @@ export async function signTransaction(...args): Promise<[Uint8Array, SignedTrans /** * Sign a delegate action - * @params.delegateAction Delegate action to be signed by the meta transaction sender - * @params.signer Signer instance for the meta transaction sender + * @options SignDelegate options + * @param options.delegateAction Delegate action to be signed by the meta transaction sender + * @param options.signer Signer instance for the meta transaction sender */ export async function signDelegateAction({ delegateAction, signer }: SignDelegateOptions): Promise { const message = encodeDelegateAction(delegateAction); diff --git a/packages/utils/src/errors/errors.ts b/packages/utils/src/errors/errors.ts index c13d04657b..474e4cfac3 100644 --- a/packages/utils/src/errors/errors.ts +++ b/packages/utils/src/errors/errors.ts @@ -2,6 +2,6 @@ import { Logger } from '../logger'; /** @deprecated */ export function logWarning(...args: any[]): void { - const [message, ...optinalParams] = args; - Logger.warn(message, ...optinalParams); + const [message, ...optionalParams] = args; + Logger.warn(message, ...optionalParams); } diff --git a/packages/utils/src/format.ts b/packages/utils/src/format.ts index 1013c332fb..1f718d6819 100644 --- a/packages/utils/src/format.ts +++ b/packages/utils/src/format.ts @@ -11,7 +11,7 @@ export const NEAR_NOMINATION_EXP = 24; */ export const NEAR_NOMINATION = new BN('10', 10).pow(new BN(NEAR_NOMINATION_EXP, 10)); -// Pre-calculate offests used for rounding to different number of digits +// Pre-calculate offsets used for rounding to different number of digits const ROUNDING_OFFSETS: BN[] = []; const BN10 = new BN(10); for (let i = 0, offset = new BN(5); i < NEAR_NOMINATION_EXP; i++, offset = offset.mul(BN10)) { diff --git a/packages/utils/src/validators.ts b/packages/utils/src/validators.ts index 30cdf63a1e..7dac43ffce 100644 --- a/packages/utils/src/validators.ts +++ b/packages/utils/src/validators.ts @@ -4,10 +4,10 @@ import depd from 'depd'; /** Finds seat price given validators stakes and number of seats. * Calculation follow the spec: https://nomicon.io/Economics/README.html#validator-selection - * @params validators: current or next epoch validators. - * @params maxNumberOfSeats: maximum number of seats in the network. - * @params minimumStakeRatio: minimum stake ratio - * @params protocolVersion: version of the protocol from genesis config + * @param validators: current or next epoch validators. + * @param maxNumberOfSeats: maximum number of seats in the network. + * @param minimumStakeRatio: minimum stake ratio + * @param protocolVersion: version of the protocol from genesis config */ export function findSeatPrice(validators: (CurrentEpochValidatorInfo | NextEpochValidatorInfo)[], maxNumberOfSeats: number, minimumStakeRatio: number[], protocolVersion?: number): BN { if (protocolVersion && protocolVersion < 49) { @@ -16,7 +16,7 @@ export function findSeatPrice(validators: (CurrentEpochValidatorInfo | NextEpoch if (!minimumStakeRatio) { const deprecate = depd('findSeatPrice(validators, maxNumberOfSeats)'); deprecate('`use `findSeatPrice(validators, maxNumberOfSeats, minimumStakeRatio)` instead'); - minimumStakeRatio = [1, 6250]; // harcoded minimumStakeRation from 12/7/21 + minimumStakeRatio = [1, 6250]; // hardcoded minimumStakeRation from 12/7/21 } return findSeatPriceForProtocolAfter49(validators, maxNumberOfSeats, minimumStakeRatio); } @@ -76,8 +76,8 @@ export interface EpochValidatorsDiff { /** Diff validators between current and next epoch. * Returns additions, subtractions and changes to validator set. - * @params currentValidators: list of current validators. - * @params nextValidators: list of next validators. + * @param currentValidators: list of current validators. + * @param nextValidators: list of next validators. */ export function diffEpochValidators(currentValidators: CurrentEpochValidatorInfo[], nextValidators: NextEpochValidatorInfo[]): EpochValidatorsDiff { const validatorsMap = new Map(); diff --git a/packages/wallet-account/src/wallet_account.ts b/packages/wallet-account/src/wallet_account.ts index bf2e421bea..18d9115b72 100644 --- a/packages/wallet-account/src/wallet_account.ts +++ b/packages/wallet-account/src/wallet_account.ts @@ -341,6 +341,11 @@ export class ConnectedWalletAccount extends Account { /** * Sign a transaction by redirecting to the NEAR Wallet * @see {@link WalletConnection#requestSignTransactions} + * @param options An optional options object + * @param options.receiverId The NEAR account ID of the transaction receiver. + * @param options.actions An array of transaction actions to be performed. + * @param options.walletMeta Additional metadata to be included in the wallet signing request. + * @param options.walletCallbackUrl URL to redirect upon completion of the wallet signing process. Default: current URL. */ async signAndSendTransaction({ receiverId, actions, walletMeta, walletCallbackUrl = window.location.href }: SignAndSendTransactionOptions): Promise { const localKey = await this.connection.signer.getPublicKey(this.accountId, this.connection.networkId); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6419e48e25..e319d6e3f1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -105,6 +105,9 @@ importers: near-hello: specifier: 0.5.1 version: 0.5.1 + near-workspaces: + specifier: 3.4.0 + version: 3.4.0 ts-jest: specifier: 26.5.6 version: 26.5.6(jest@26.0.1)(typescript@4.9.4) @@ -391,6 +394,9 @@ importers: near-hello: specifier: 0.5.1 version: 0.5.1 + near-workspaces: + specifier: 3.4.0 + version: 3.4.0 rimraf: specifier: 3.0.2 version: 3.0.2 @@ -435,6 +441,9 @@ importers: jest: specifier: 26.0.1 version: 26.0.1 + near-workspaces: + specifier: 3.4.0 + version: 3.4.0 ts-jest: specifier: 26.5.6 version: 26.5.6(jest@26.0.1)(typescript@4.9.4) @@ -1715,6 +1724,121 @@ packages: read-yaml-file: 1.1.0 dev: true + /@near-js/accounts@0.1.4: + resolution: {integrity: sha512-zHFmL4OUZ4qHXOE+dDBkYgTNHLWC5RmYUVp9LiuGciO5zFPp7WlxmowJL0QjgXqV1w+dNXq3mgmkfAgYVS8Xjw==} + dependencies: + '@near-js/crypto': 0.0.5 + '@near-js/providers': 0.0.7 + '@near-js/signers': 0.0.5 + '@near-js/transactions': 0.2.1 + '@near-js/types': 0.0.4 + '@near-js/utils': 0.0.4 + ajv: 8.11.2 + ajv-formats: 2.1.1(ajv@8.11.2) + bn.js: 5.2.1 + borsh: 0.7.0 + depd: 2.0.0 + near-abi: 0.1.1 + transitivePeerDependencies: + - encoding + dev: true + + /@near-js/crypto@0.0.5: + resolution: {integrity: sha512-nbQ971iYES5Spiolt+p568gNuZ//HeMHm3qqT3xT+i8ZzgbC//l6oRf48SUVTPAboQ1TJ5dW/NqcxOY0pe7b4g==} + dependencies: + '@near-js/types': 0.0.4 + bn.js: 5.2.1 + borsh: 0.7.0 + tweetnacl: 1.0.3 + dev: true + + /@near-js/keystores-browser@0.0.5: + resolution: {integrity: sha512-mHF3Vcvsr7xnkaM/reOyxtykbE3OWKV6vQzqyTH2tZYT2OTEnj0KhRT9BCFC0Ra67K1zQLbg49Yc/kDCc5qupA==} + dependencies: + '@near-js/crypto': 0.0.5 + '@near-js/keystores': 0.0.5 + dev: true + + /@near-js/keystores-node@0.0.5: + resolution: {integrity: sha512-BYmWyGNydfAqi7eYA1Jo8zULL13cxejD2VBr0BBIXx5bJ+BO4TLecsY1xdTBEq06jyWXHa7kV4h8BJzAjvpTLg==} + dependencies: + '@near-js/crypto': 0.0.5 + '@near-js/keystores': 0.0.5 + dev: true + + /@near-js/keystores@0.0.5: + resolution: {integrity: sha512-kxqV+gw/3L8/axe9prhlU+M0hfybkxX54xfI0EEpWP2QiUV+qw+jkKolYIbdk5tdEZrGf9jHawh1yFtwP7APPQ==} + dependencies: + '@near-js/crypto': 0.0.5 + '@near-js/types': 0.0.4 + dev: true + + /@near-js/providers@0.0.7: + resolution: {integrity: sha512-qj16Ey+vSw7lHE85xW+ykYJoLPr4A6Q/TsfpwhJLS6zBInSC6sKVqPO1L8bK4VA/yB7V7JJPor9UVCWgRXdNEA==} + dependencies: + '@near-js/transactions': 0.2.1 + '@near-js/types': 0.0.4 + '@near-js/utils': 0.0.4 + bn.js: 5.2.1 + borsh: 0.7.0 + http-errors: 1.7.2 + optionalDependencies: + node-fetch: 2.6.7 + transitivePeerDependencies: + - encoding + dev: true + + /@near-js/signers@0.0.5: + resolution: {integrity: sha512-XJjYYatehxHakHa7WAoiQ8uIBSWBR2EnO4GzlIe8qpWL+LoH4t68MSezC1HwT546y9YHIvePjwDrBeYk8mg20w==} + dependencies: + '@near-js/crypto': 0.0.5 + '@near-js/keystores': 0.0.5 + js-sha256: 0.9.0 + dev: true + + /@near-js/transactions@0.2.1: + resolution: {integrity: sha512-V9tXzkICDPruSxihKXkBhUgsI4uvW7TwXlnZS2GZpPsFFiIUeGrso0wo4uiQwB6miFA5q6fKaAtQa4F2v1s+zg==} + dependencies: + '@near-js/crypto': 0.0.5 + '@near-js/signers': 0.0.5 + '@near-js/types': 0.0.4 + '@near-js/utils': 0.0.4 + bn.js: 5.2.1 + borsh: 0.7.0 + js-sha256: 0.9.0 + dev: true + + /@near-js/types@0.0.4: + resolution: {integrity: sha512-8TTMbLMnmyG06R5YKWuS/qFG1tOA3/9lX4NgBqQPsvaWmDsa+D+QwOkrEHDegped0ZHQwcjAXjKML1S1TyGYKg==} + dependencies: + bn.js: 5.2.1 + dev: true + + /@near-js/utils@0.0.4: + resolution: {integrity: sha512-mPUEPJbTCMicGitjEGvQqOe8AS7O4KkRCxqd0xuE/X6gXF1jz1pYMZn4lNUeUz2C84YnVSGLAM0o9zcN6Y4hiA==} + dependencies: + '@near-js/types': 0.0.4 + bn.js: 5.2.1 + depd: 2.0.0 + mustache: 4.0.0 + dev: true + + /@near-js/wallet-account@0.0.7: + resolution: {integrity: sha512-tmRyieG/wHmuNkg/WGFyKD6iH6atHPbY0rZ5OjOIiteuhZEPgp+z8OBpiQ4qumTa63q46aj/QVSQL0J3+JmBfw==} + dependencies: + '@near-js/accounts': 0.1.4 + '@near-js/crypto': 0.0.5 + '@near-js/keystores': 0.0.5 + '@near-js/signers': 0.0.5 + '@near-js/transactions': 0.2.1 + '@near-js/types': 0.0.4 + '@near-js/utils': 0.0.4 + bn.js: 5.2.1 + borsh: 0.7.0 + transitivePeerDependencies: + - encoding + dev: true + /@noble/curves@1.2.0: resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} dependencies: @@ -1885,6 +2009,11 @@ packages: webcrypto-core: 1.7.7 dev: false + /@sindresorhus/is@4.6.0: + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} + dev: true + /@sinonjs/commons@1.8.6: resolution: {integrity: sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==} dependencies: @@ -1897,6 +2026,13 @@ packages: '@sinonjs/commons': 1.8.6 dev: true + /@szmarczak/http-timer@4.0.6: + resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} + engines: {node: '>=10'} + dependencies: + defer-to-connect: 2.0.1 + dev: true + /@tootallnate/once@1.1.2: resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} engines: {node: '>= 6'} @@ -1953,12 +2089,25 @@ packages: '@types/node': 18.11.18 dev: true + /@types/cacheable-request@6.0.3: + resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} + dependencies: + '@types/http-cache-semantics': 4.0.4 + '@types/keyv': 3.1.4 + '@types/node': 18.11.18 + '@types/responselike': 1.0.3 + dev: true + /@types/graceful-fs@4.1.6: resolution: {integrity: sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==} dependencies: '@types/node': 18.11.18 dev: true + /@types/http-cache-semantics@4.0.4: + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + dev: true + /@types/http-errors@1.6.1: resolution: {integrity: sha512-s+RHKSGc3r0m3YEE2UXomJYrpQaY9cDmNDLU2XvG1/LAZsQ7y8emYkTLfcw/ByDtcsTyRQKwr76Bj4PkN2hfWg==} dev: true @@ -1988,6 +2137,12 @@ packages: /@types/json-schema@7.0.12: resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} + /@types/keyv@3.1.4: + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + dependencies: + '@types/node': 18.11.18 + dev: true + /@types/minimist@1.2.2: resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} dev: true @@ -2008,6 +2163,12 @@ packages: resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} dev: true + /@types/responselike@1.0.3: + resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} + dependencies: + '@types/node': 18.11.18 + dev: true + /@types/semver@6.2.3: resolution: {integrity: sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A==} dev: true @@ -2242,7 +2403,6 @@ packages: optional: true dependencies: ajv: 8.11.2 - dev: false /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -2537,9 +2697,20 @@ packages: dependencies: safe-buffer: 5.2.1 + /base-x@3.0.9: + resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + /base64url@3.0.1: + resolution: {integrity: sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==} + engines: {node: '>=6.0.0'} + dev: true + /base@0.11.2: resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} engines: {node: '>=0.10.0'} @@ -2571,6 +2742,22 @@ packages: /bn.js@5.2.1: resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + /borsh@0.5.0: + resolution: {integrity: sha512-p9w/qGBeeFdUf2GPBPHdX5JQyez8K5VtoFN7PqSfmR+cVUMSmcwAKhP9n2aXoDSKbtS7xZlZt3MVnrJL7GdYhg==} + dependencies: + bn.js: 5.2.1 + bs58: 4.0.0 + text-encoding-utf-8: 1.0.2 + dev: true + + /borsh@0.7.0: + resolution: {integrity: sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==} + dependencies: + bn.js: 5.2.1 + bs58: 4.0.0 + text-encoding-utf-8: 1.0.2 + dev: true + /borsh@1.0.0: resolution: {integrity: sha512-fSVWzzemnyfF89EPwlUNsrS5swF5CrtiN4e+h0/lLf4dz2he4L3ndM20PS9wj7ICSkXJe/TQUHdaPTq15b1mNQ==} dev: false @@ -2784,6 +2971,12 @@ packages: dependencies: base-x: 2.0.6 + /bs58@4.0.1: + resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + dependencies: + base-x: 3.0.9 + dev: true + /bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} dependencies: @@ -2864,6 +3057,24 @@ packages: unset-value: 1.0.0 dev: true + /cacheable-lookup@5.0.4: + resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} + engines: {node: '>=10.6.0'} + dev: true + + /cacheable-request@7.0.4: + resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} + engines: {node: '>=8'} + dependencies: + clone-response: 1.0.3 + get-stream: 5.2.0 + http-cache-semantics: 4.1.1 + keyv: 4.5.4 + lowercase-keys: 2.0.0 + normalize-url: 6.1.0 + responselike: 2.0.1 + dev: true + /cached-path-relative@1.1.0: resolution: {integrity: sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==} dev: true @@ -2880,6 +3091,11 @@ packages: engines: {node: '>=6'} dev: true + /callsites@4.1.0: + resolution: {integrity: sha512-aBMbD1Xxay75ViYezwT40aQONfr+pSXTHwNKvIXhXD6+LY3F1dLIcceoC5OZKBVHbXcysz1hL9D2w0JJIMXpUw==} + engines: {node: '>=12.20'} + dev: true + /camelcase-keys@6.2.2: resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} engines: {node: '>=8'} @@ -2903,6 +3119,10 @@ packages: resolution: {integrity: sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==} dev: true + /capability@0.2.5: + resolution: {integrity: sha512-rsJZYVCgXd08sPqwmaIqjAd5SUTfonV0z/gDJ8D6cN8wQphky1kkAYEqQ+hmDxTw7UihvBfjUVUSY+DBEe44jg==} + dev: true + /capture-exit@2.0.0: resolution: {integrity: sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==} engines: {node: 6.* || 8.* || >= 10.*} @@ -2965,6 +3185,11 @@ packages: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} dev: true + /chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: true + /ci-env@1.17.0: resolution: {integrity: sha512-NtTjhgSEqv4Aj90TUYHQLxHdnCPXnjdtuGG1X8lTfp/JqeXTdw0FTWl/vUAPuvbWZTF8QVpv6ASe/XacE+7R2A==} dev: true @@ -3016,6 +3241,12 @@ packages: wrap-ansi: 7.0.0 dev: true + /clone-response@1.0.3: + resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} + dependencies: + mimic-response: 1.0.1 + dev: true + /clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} @@ -3496,6 +3727,13 @@ packages: engines: {node: '>=0.10'} dev: true + /decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + dependencies: + mimic-response: 3.1.0 + dev: true + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true @@ -3511,6 +3749,11 @@ packages: clone: 1.0.4 dev: true + /defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + dev: true + /define-properties@1.2.0: resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} engines: {node: '>= 0.4'} @@ -3553,12 +3796,10 @@ packages: /depd@1.1.2: resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} engines: {node: '>= 0.6'} - dev: false /depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} - dev: false /deprecation@2.3.1: resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} @@ -3726,6 +3967,14 @@ packages: is-arrayish: 0.2.1 dev: true + /error-polyfill@0.1.3: + resolution: {integrity: sha512-XHJk60ufE+TG/ydwp4lilOog549iiQF2OAPhkk9DdiYWMrltz5yhDz/xnKuenNwP7gy3dsibssO5QpVhkrSzzg==} + dependencies: + capability: 0.2.5 + o3: 1.0.3 + u3: 0.1.1 + dev: true + /es-abstract@1.22.1: resolution: {integrity: sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==} engines: {node: '>= 0.4'} @@ -4286,6 +4535,15 @@ packages: engines: {node: '>=0.10.0'} dev: true + /fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + /fs-extra@11.1.1: resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} engines: {node: '>=14.14'} @@ -4313,6 +4571,13 @@ packages: universalify: 0.1.2 dev: true + /fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: true + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true @@ -4518,6 +4783,23 @@ packages: get-intrinsic: 1.2.1 dev: true + /got@11.8.6: + resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} + engines: {node: '>=10.19.0'} + dependencies: + '@sindresorhus/is': 4.6.0 + '@szmarczak/http-timer': 4.0.6 + '@types/cacheable-request': 6.0.3 + '@types/responselike': 1.0.3 + cacheable-lookup: 5.0.4 + cacheable-request: 7.0.4 + decompress-response: 6.0.0 + http2-wrapper: 1.0.3 + lowercase-keys: 2.0.0 + p-cancelable: 2.1.1 + responselike: 2.0.1 + dev: true + /graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} dev: true @@ -4697,6 +4979,10 @@ packages: engines: {node: '>=0.10'} dev: true + /http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + dev: true + /http-errors@1.7.2: resolution: {integrity: sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==} engines: {node: '>= 0.6'} @@ -4706,7 +4992,6 @@ packages: setprototypeof: 1.1.1 statuses: 1.5.0 toidentifier: 1.0.0 - dev: false /http-proxy-agent@2.1.0: resolution: {integrity: sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==} @@ -4729,6 +5014,14 @@ packages: - supports-color dev: true + /http2-wrapper@1.0.3: + resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} + engines: {node: '>=10.19.0'} + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + dev: true + /https-browserify@1.0.0: resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} dev: true @@ -5690,6 +5983,10 @@ packages: resolution: {integrity: sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==} dev: false + /js-sha256@0.9.0: + resolution: {integrity: sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==} + dev: true + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: true @@ -5757,6 +6054,10 @@ packages: hasBin: true dev: true + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + /json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} dev: true @@ -5851,6 +6152,12 @@ packages: safe-buffer: 5.2.1 dev: true + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + /kind-of@3.2.2: resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} engines: {node: '>=0.10.0'} @@ -6055,6 +6362,11 @@ packages: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} dev: true + /lowercase-keys@2.0.0: + resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} + engines: {node: '>=8'} + dev: true + /lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} dependencies: @@ -6241,6 +6553,16 @@ packages: engines: {node: '>=6'} dev: true + /mimic-response@1.0.1: + resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} + engines: {node: '>=4'} + dev: true + + /mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + dev: true + /min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -6280,6 +6602,26 @@ packages: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: true + /minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: true + + /minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + dev: true + + /minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + dev: true + /mixin-deep@1.3.2: resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} engines: {node: '>=0.10.0'} @@ -6344,7 +6686,6 @@ packages: resolution: {integrity: sha512-FJgjyX/IVkbXBXYUwH+OYwQKqWpFPLaLVESd70yHjSDunwzV2hZOoTBvPf4KLoxesUzzyfTH6F784Uqd7Wm5yA==} engines: {npm: '>=1.4.0'} hasBin: true - dev: false /nanomatch@1.2.13: resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} @@ -6373,12 +6714,80 @@ packages: resolution: {integrity: sha512-RVDI8O+KVxRpC3KycJ1bpfVj9Zv+xvq9PlW1yIFl46GhrnLw83/72HqHGjGDjQ8DtltkcpSjY9X3YIGZ+1QyzQ==} dependencies: '@types/json-schema': 7.0.12 - dev: false + + /near-api-js@2.1.4: + resolution: {integrity: sha512-e1XicyvJvQMtu7qrG8oWyAdjHJJCoy+cvbW6h2Dky4yj7vC85omQz/x7IgKl71VhzDj2/TGUwjTVESp6NSe75A==} + dependencies: + '@near-js/accounts': 0.1.4 + '@near-js/crypto': 0.0.5 + '@near-js/keystores': 0.0.5 + '@near-js/keystores-browser': 0.0.5 + '@near-js/keystores-node': 0.0.5 + '@near-js/providers': 0.0.7 + '@near-js/signers': 0.0.5 + '@near-js/transactions': 0.2.1 + '@near-js/types': 0.0.4 + '@near-js/utils': 0.0.4 + '@near-js/wallet-account': 0.0.7 + ajv: 8.11.2 + ajv-formats: 2.1.1(ajv@8.11.2) + bn.js: 5.2.1 + borsh: 0.7.0 + depd: 2.0.0 + error-polyfill: 0.1.3 + http-errors: 1.7.2 + near-abi: 0.1.1 + node-fetch: 2.6.7 + tweetnacl: 1.0.3 + transitivePeerDependencies: + - encoding + dev: true /near-hello@0.5.1: resolution: {integrity: sha512-k7S8VFyESWgkKYDso99B4XbxAdo0VX9b3+GAaO5PvMgQjNr/6o09PHRywg/NkBQpf+ZYj7nNpJcyrNJGQsvA3w==} dev: true + /near-sandbox@0.0.15: + resolution: {integrity: sha512-scFdPDoT8G0GteHJID8KLZQNGtg7zpjBnRZUZTjXVO8atKzHYw8iawpc+ekylErn5bbWG49Tv4KySBUv4chIRA==} + hasBin: true + requiresBuild: true + dependencies: + got: 11.8.6 + tar: 6.2.0 + dev: true + + /near-units@0.1.9: + resolution: {integrity: sha512-xiuBjpNsi+ywiu7P6iWRZdgFm7iCr/cfWlVO6+e5uaAqH4mE1rrurElyrL91llNDSnMwogd9XmlZOw5KbbHNsA==} + hasBin: true + dependencies: + bn.js: 5.2.1 + dev: true + + /near-workspaces@3.4.0: + resolution: {integrity: sha512-OjBUXtNaYCRgUTyAw1rarDVElzggYszAGDR62x9gHscSNhAkLiCLP0jF8BHnuF0CL/XWuQtNeLS9m91KdieytQ==} + engines: {node: '>= 14.0.0', npm: '>= 6.0.0'} + requiresBuild: true + dependencies: + base64url: 3.0.1 + bn.js: 5.2.1 + borsh: 0.5.0 + bs58: 4.0.1 + callsites: 4.1.0 + fs-extra: 10.1.0 + js-sha256: 0.9.0 + near-api-js: 2.1.4 + near-sandbox: 0.0.15 + near-units: 0.1.9 + node-port-check: 2.0.1 + promisify-child-process: 4.1.2 + proper-lockfile: 4.1.2 + pure-uuid: 1.8.1 + rimraf: 3.0.2 + temp-dir: 2.0.0 + transitivePeerDependencies: + - encoding + dev: true + /nice-try@1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} dev: true @@ -6428,6 +6837,10 @@ packages: dev: true optional: true + /node-port-check@2.0.1: + resolution: {integrity: sha512-PV1tj5OPbWwxvhPcChXxwCIKl/IfVEdPP4u/gQz2lao/VGoeIUXb/4U72KSHLZpTVBmgTnMm0me7yR0wUsIuPg==} + dev: true + /node-releases@2.0.13: resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} dev: true @@ -6463,6 +6876,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + dev: true + /npm-run-path@2.0.2: resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} engines: {node: '>=4'} @@ -6481,6 +6899,12 @@ packages: resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} dev: true + /o3@1.0.3: + resolution: {integrity: sha512-f+4n+vC6s4ysy7YO7O2gslWZBUu8Qj2i2OUJOvjRxQva7jVjYjB29jrr9NCjmxZQR0gzrOcv1RnqoYOeMs5VRQ==} + dependencies: + capability: 0.2.5 + dev: true + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -6570,6 +6994,11 @@ packages: resolution: {integrity: sha512-eoJ9YWxFcXbrn2U8FKT6RV+/Kj7fiGAB1VvHzbYKt8xM5ZuKZgCGvnHzDxmreEjcBH28ejg5MiOH4iyY1mQnkg==} dev: true + /p-cancelable@2.1.1: + resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} + engines: {node: '>=8'} + dev: true + /p-each-series@2.2.0: resolution: {integrity: sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==} engines: {node: '>=8'} @@ -6844,6 +7273,11 @@ packages: engines: {node: '>= 0.6.0'} dev: true + /promisify-child-process@4.1.2: + resolution: {integrity: sha512-APnkIgmaHNJpkAn7k+CrJSi9WMuff5ctYFbD0CO2XIPkM8yO7d/ShouU2clywbpHV/DUsyc4bpJCsNgddNtx4g==} + engines: {node: '>=8'} + dev: true + /prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} @@ -6852,6 +7286,14 @@ packages: sisteransi: 1.0.5 dev: true + /proper-lockfile@4.1.2: + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + dependencies: + graceful-fs: 4.2.11 + retry: 0.12.0 + signal-exit: 3.0.7 + dev: true + /pseudomap@1.0.2: resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} dev: true @@ -6886,6 +7328,11 @@ packages: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} + /pure-uuid@1.8.1: + resolution: {integrity: sha512-PIwHXU7NZb/wTBwUfzCSjI85tfwx6DQOm74sRLtNLH8KHsFZEvAQbBQdz7E5ij8SNSv9WGdQPWiiM6NpNIeNfA==} + engines: {node: '>=8.0.0'} + dev: true + /pvtsutils@1.3.2: resolution: {integrity: sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ==} dependencies: @@ -6937,6 +7384,11 @@ packages: engines: {node: '>=8'} dev: true + /quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + dev: true + /randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: @@ -7079,6 +7531,10 @@ packages: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} dev: true + /resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + dev: true + /resolve-cwd@3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} engines: {node: '>=8'} @@ -7121,6 +7577,12 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true + /responselike@2.0.1: + resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + dependencies: + lowercase-keys: 2.0.0 + dev: true + /ret@0.1.15: resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} engines: {node: '>=0.12'} @@ -7276,7 +7738,6 @@ packages: /setprototypeof@1.1.1: resolution: {integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==} - dev: false /sha.js@2.4.11: resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} @@ -7522,7 +7983,6 @@ packages: /statuses@1.5.0: resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} engines: {node: '>= 0.6'} - dev: false /stream-browserify@2.0.2: resolution: {integrity: sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==} @@ -7716,6 +8176,23 @@ packages: acorn-node: 1.8.2 dev: true + /tar@6.2.0: + resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} + engines: {node: '>=10'} + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + dev: true + + /temp-dir@2.0.0: + resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} + engines: {node: '>=8'} + dev: true + /term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} @@ -7749,6 +8226,10 @@ packages: minimatch: 3.1.2 dev: true + /text-encoding-utf-8@1.0.2: + resolution: {integrity: sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==} + dev: true + /text-extensions@1.9.0: resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==} engines: {node: '>=0.10'} @@ -7852,7 +8333,6 @@ packages: /toidentifier@1.0.0: resolution: {integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==} engines: {node: '>=0.6'} - dev: false /tough-cookie@4.1.3: resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} @@ -8131,6 +8611,10 @@ packages: turbo-windows-arm64: 1.4.5 dev: true + /tweetnacl@1.0.3: + resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} + dev: true + /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -8241,6 +8725,10 @@ packages: hasBin: true dev: true + /u3@0.1.1: + resolution: {integrity: sha512-+J5D5ir763y+Am/QY6hXNRlwljIeRMZMGs0cT6qqZVVzzT3X3nFPXVyPOFRMOR4kupB0T8JnCdpWdp6Q/iXn3w==} + dev: true + /uglifyify@5.0.1: resolution: {integrity: sha512-PO44rgExvwj3rkK0UzenHVnPU18drBy9x9HOUmgkuRh6K2KIsDqrB5LqxGtjybgGTOS1JeP8SBc+TN5rhiva6w==} dependencies: