diff --git a/.gitignore b/.gitignore index 543e952..94819d4 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,4 @@ fileScript-add.js log*.md accounts.csv /keys +Token.json \ No newline at end of file diff --git a/anchor/admin/createService.ts b/anchor/admin/createService.ts index b54b1ea..21bb46b 100644 --- a/anchor/admin/createService.ts +++ b/anchor/admin/createService.ts @@ -24,6 +24,7 @@ export async function createService( price: number, serviceDescription: string, uniqueId: string, + serviceProviderTokenAccount: PublicKey, ) { await program.methods .initializeService( @@ -35,6 +36,7 @@ export async function createService( provider: serviceDeployer.publicKey, serviceRegistry: serviceRegistryPubkey, mint: _mint, + serviceProviderTokenAccount, tokenProgram: TOKEN_PROGRAM_ID, }) .signers([serviceDeployer]) // Include both deployer and the new service keypair as signers diff --git a/anchor/admin/deploy-registry.ts b/anchor/admin/deploy-registry.ts index f52f67f..be7e241 100644 --- a/anchor/admin/deploy-registry.ts +++ b/anchor/admin/deploy-registry.ts @@ -1,17 +1,19 @@ import * as dotenv from 'dotenv'; +import * as fs from 'fs'; // Import the fs module import { Program, workspace, setProvider } from '@coral-xyz/anchor'; - import { Connection, SystemProgram, Transaction, sendAndConfirmTransaction, + PublicKey, } from '@solana/web3.js'; import { Gigentic } from '../target/types/gigentic'; import { PROVIDER } from '../tests/constants'; -import { loadKeypairBs58FromEnv } from '../tests/utils'; +import { airdrop, loadKeypairBs58FromEnv } from '../tests/utils'; +import { createMintToken, createTokenAccount } from './init'; dotenv.config(); @@ -39,6 +41,29 @@ console.log('serviceRegistry', serviceRegistryKeypair.publicKey.toString()); async function initServiceRegistry() { try { + const mint: PublicKey = + (await createMintToken(connection, serviceRegistryDeployer)) || + new PublicKey(0); // Provide a default value or handle the error appropriately + console.log('Mint Public Key:', mint.toString()); + + const feeTokenAccount: PublicKey = await createTokenAccount( + connection, + serviceRegistryDeployer, + mint, + ); + + // Create a JSON object to write to a file + const output = { + mintPublicKey: mint, + feeTokenAccountPublicKey: feeTokenAccount, + }; + fs.writeFileSync('Token.json', JSON.stringify(output, null, 2)); // Write to Token.json + + // Add the fee token account to the output + output.feeTokenAccountPublicKey = feeTokenAccount; // Ensure this is included + fs.writeFileSync('Token.json', JSON.stringify(output, null, 2)); // Write to Token.json again + console.log('Fee Token Account Public Key:', feeTokenAccount.toString()); + const feeAccount = serviceRegistryDeployer.publicKey; console.log('Fee Account Public Key:', feeAccount.toString()); @@ -46,13 +71,15 @@ async function initServiceRegistry() { console.log('Fee Percentage:', feePercentage); // Create the service registry account - const serviceRegistryAccountSize = 20000; // Adjust the size based on the ServiceRegistry struct + const serviceRegistryAccountSize = 2000; // Adjust the size based on the ServiceRegistry struct console.log('Service Registry Account Size: ', serviceRegistryAccountSize); + const rentExemptionAmount = await connection.getMinimumBalanceForRentExemption( serviceRegistryAccountSize, ); console.log('Rent Exemption Amount: ', rentExemptionAmount); + const createAccountParams = { fromPubkey: serviceRegistryDeployer.publicKey, // Account paying for the creation of the new account newAccountPubkey: serviceRegistryKeypair.publicKey, // Public key of the new account to be created @@ -69,7 +96,7 @@ async function initServiceRegistry() { ]); const transactionSignature = await program.methods - .initializeServiceRegistry(feeAccount, feePercentage) + .initializeServiceRegistry(feeAccount, feeTokenAccount, feePercentage) .accounts({ initializer: serviceRegistryDeployer.publicKey, serviceRegistry: serviceRegistryKeypair.publicKey, @@ -90,29 +117,14 @@ async function initServiceRegistry() { async function main() { try { - console.log('========== Airdrop serviceRegistry deployer'); + // console.log('========== Airdrop serviceRegistry deployer'); // await airdrop(connection, serviceRegistryDeployer.publicKey); - console.log('skip airdrop serviceRegistryDeployer'); - console.log('\n'); + // console.log('skip airdrop serviceRegistryDeployer'); + // console.log('\n'); console.log('========== Initialize service registry'); await initServiceRegistry(); console.log('\n'); - - console.log('========== Read service registry'); - const serviceRegistry = await program.account.serviceRegistry.fetch( - serviceRegistryKeypair.publicKey, - ); - - for (const serviceAddress of serviceRegistry.serviceAccountAddresses) { - console.log('Service Account Address:', serviceAddress.toString()); - - const serviceAccount = - await program.account.service.fetch(serviceAddress); - // console.log('Service Account Unique ID:', serviceAccount.uniqueId); - console.log('Service Account Description:', serviceAccount.description); - console.log('Service Account Price:', serviceAccount.price.toString()); - } } catch (error) { console.error('Error in main execution:', error); } diff --git a/anchor/admin/init.ts b/anchor/admin/init.ts new file mode 100644 index 0000000..09c3454 --- /dev/null +++ b/anchor/admin/init.ts @@ -0,0 +1,42 @@ +import { createMint } from '@solana/spl-token'; +import { createAccount } from '@solana/spl-token'; +import { PublicKey, Keypair } from '@solana/web3.js'; + +import { Connection } from '@solana/web3.js'; + +export async function createMintToken( + connection: Connection, + deployer: Keypair, +) { + try { + const mint = await createMint( + connection, + deployer, // payer FEE + deployer.publicKey, // owner, mint authority who can mint new tokens + deployer.publicKey, // freeze authority + 8, + ); + return mint; + } catch (error) { + console.error('Error creating mint token:', error); + } +} + +export async function createTokenAccount( + connection: Connection, + payerKeypair: Keypair, + mint: PublicKey, +): Promise { + try { + const tokenAccount: PublicKey = await createAccount( + connection, + payerKeypair, // Payer + mint, // Mint + payerKeypair.publicKey, // Owner + ); + return tokenAccount; + } catch (error) { + console.error('Error creating token account:', error); + throw new Error('Failed to create token account'); + } +} diff --git a/anchor/admin/write-services.ts b/anchor/admin/write-services.ts index c6071d2..6cf3bfa 100644 --- a/anchor/admin/write-services.ts +++ b/anchor/admin/write-services.ts @@ -1,19 +1,19 @@ import * as dotenv from 'dotenv'; +import * as fs from 'fs'; import { Program, workspace, setProvider } from '@coral-xyz/anchor'; -import { createMint } from '@solana/spl-token'; - import { Connection, LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js'; -import { services } from './Services'; // Import services from Services.ts import { Gigentic } from '../target/types/gigentic'; import { PROVIDER } from '../tests/constants'; import { airdrop, loadKeypairBs58FromEnv } from '../tests/utils'; - +import { createTokenAccount } from './init'; import { createService } from './createService'; +import { services } from './Services'; + dotenv.config(); -// Configure the client to use the local cluster +// Use cluster configured in local CLI environment setProvider(PROVIDER); // Initialize connection and program @@ -24,88 +24,81 @@ const program: Program = workspace.Gigentic as Program; const serviceRegistryDeployer = loadKeypairBs58FromEnv( 'SERVICE_REGISTRY_DEPLOYER_KEYPAIR', ); -const serviceRegistryKeypair = loadKeypairBs58FromEnv( - 'SERVICE_REGISTRY_KEYPAIR', -); console.log( - 'serviceRegistryDeployer', + 'Service Registry Deployer Public Key:', serviceRegistryDeployer.publicKey.toString(), ); + +const serviceRegistryKeypair = loadKeypairBs58FromEnv( + 'SERVICE_REGISTRY_KEYPAIR', +); console.log( - 'serviceRegistryKeypair', + 'Service Registry Keypair Public Key:', serviceRegistryKeypair.publicKey.toString(), ); // Load service deployer keypair const serviceDeployer = loadKeypairBs58FromEnv('SERVICE_DEPLOYER_KEYPAIR'); -console.log('serviceDeployer', serviceDeployer.publicKey.toString()); - -let mint: PublicKey; - -async function createMintToken() { - try { - mint = await createMint( - connection, - serviceRegistryDeployer, - serviceRegistryDeployer.publicKey, - serviceRegistryDeployer.publicKey, - 8, - ); - console.log('Mint token created:', mint.toString()); - } catch (error) { - console.error('Error creating mint token:', error); - } -} +console.log( + 'Service Deployer Public Key:', + serviceDeployer.publicKey.toString(), +); async function main() { try { - console.log('========== Create mint token'); - await createMintToken(); - console.log('\n'); + // console.log('========== Airdrop for Service Deployer =========='); + // await airdrop(connection, serviceDeployer.publicKey); + // console.log('Airdrop completed successfully.\n'); + // console.log('skip airdrop serviceDeployer'); + + const data = fs.readFileSync('Token.json', 'utf-8'); + const parsedData = JSON.parse(data); + const tokenMint = new PublicKey(parsedData.mintPublicKey); - console.log('========== Airdrop service deployer'); - await airdrop(connection, serviceDeployer.publicKey); - console.log('\n'); + // Creating a token account + const serviceProviderTokenAccount = await createTokenAccount( + connection, + serviceDeployer, + tokenMint, + ); - console.log('========== Prepare data and Create services'); - console.log('\n'); + // Update Token.json with the service provider token account + parsedData.serviceProviderTokenAccountPublicKey = + serviceProviderTokenAccount; + fs.writeFileSync('Token.json', JSON.stringify(parsedData, null, 2)); + console.log('========== Prepare Data and Create Services =========='); let index = 0; for (const service of services) { const description = `chatWalletAddress: ${service.chatWalletAddress} | title: ${service.title} | experience: ${service.experience} | price: ${service.price} ${service.currency} | avgRating: ${service.avgRating}`; - console.log(description); - - // Update to use services array - const uniqueId = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`; console.log( - `Creating service ${index + 1}/${services.length} with ID ${uniqueId}:`, + `Creating service ${index + 1}/${services.length}: ${description}`, ); + + const uniqueId = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`; await createService( serviceRegistryKeypair.publicKey, - mint, + tokenMint, program, - LAMPORTS_PER_SOL * service.price, // Use price from services - description, // Use description from services - // index.toString(), // unique id + LAMPORTS_PER_SOL * service.price, + description, uniqueId, + serviceProviderTokenAccount, ); index++; } - console.log('========== Fetch service registry'); + console.log('========== Fetch Service Registry =========='); const serviceRegistry = await program.account.serviceRegistry.fetch( serviceRegistryKeypair.publicKey, ); - for (const serviceAddress of serviceRegistry.serviceAccountAddresses) { - console.log('Service Account Address:', serviceAddress.toString()); - const serviceAccount = await program.account.service.fetch(serviceAddress); - console.log('Service Account Description:', serviceAccount.description); - console.log('Service Account Price:', serviceAccount.price.toString()); - // console.log('Service Account Mint:', serviceAccount.mint.toString()); + console.log(`Service Account Address: ${serviceAddress.toString()}`); + console.log(`Service Account Description: ${serviceAccount.description}`); + console.log(`Service Account Price: ${serviceAccount.price.toString()}`); } } catch (error) { console.error('Error in main execution:', error); diff --git a/anchor/programs/gigentic/Cargo.toml b/anchor/programs/gigentic/Cargo.toml index ff3e64c..1554655 100644 --- a/anchor/programs/gigentic/Cargo.toml +++ b/anchor/programs/gigentic/Cargo.toml @@ -17,5 +17,5 @@ default = [] idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"] [dependencies] -anchor-lang = "0.30.1" +anchor-lang = "0.30.1" anchor-spl = "0.30.1" diff --git a/anchor/programs/gigentic/src/contexts/customer_to_provider_rating.rs b/anchor/programs/gigentic/src/contexts/customer_to_provider_rating.rs index 23900a4..8b125b7 100644 --- a/anchor/programs/gigentic/src/contexts/customer_to_provider_rating.rs +++ b/anchor/programs/gigentic/src/contexts/customer_to_provider_rating.rs @@ -7,9 +7,9 @@ pub struct ReviewCustomerToProviderService<'info> { // The account of the user deploying and paying for the initialization. // Marked as `mut` because it will be charged for rent. #[account(mut)] - pub signer: Signer<'info>, + pub customer: Signer<'info>, - #[account(mut, constraint = review.customer == signer.key())] + #[account(mut, constraint = review.customer == customer.key())] pub review: Account<'info, Review>, pub system_program: Program<'info, System>, diff --git a/anchor/programs/gigentic/src/contexts/init_service.rs b/anchor/programs/gigentic/src/contexts/init_service.rs index 21552c3..2f9c5c8 100644 --- a/anchor/programs/gigentic/src/contexts/init_service.rs +++ b/anchor/programs/gigentic/src/contexts/init_service.rs @@ -1,6 +1,9 @@ -use crate::states::{service_registry::ServiceRegistry, Service}; +use crate::states::{ + service_authority::ServiceAuthority, service_registry::ServiceRegistry, Service, +}; use crate::ErrorCode; use anchor_lang::prelude::*; +use anchor_spl::token::TokenAccount; use anchor_spl::token_interface::{Mint, TokenInterface}; #[derive(Accounts)] @@ -24,6 +27,17 @@ pub struct InitializeService<'info> { )] service: Account<'info, Service>, + pub service_provider_token_account: Account<'info, TokenAccount>, + + #[account( + init, + payer = provider, + space = 8, + seeds = ["service_authority".as_bytes(), service.key().as_ref()], + bump + )] + service_authority: Account<'info, ServiceAuthority>, + // The mint account for the token #[account( mint::token_program = token_program @@ -74,8 +88,8 @@ impl<'info> InitializeService<'info> { description, price, reviews: Vec::new(), // Initialize reviews as an empty vector + service_provider_token_account: self.service_provider_token_account.key(), }); - Ok(()) } } diff --git a/anchor/programs/gigentic/src/contexts/init_service_registry.rs b/anchor/programs/gigentic/src/contexts/init_service_registry.rs index 4fcb297..8c0b6c0 100644 --- a/anchor/programs/gigentic/src/contexts/init_service_registry.rs +++ b/anchor/programs/gigentic/src/contexts/init_service_registry.rs @@ -19,12 +19,19 @@ pub struct InitServiceRegistry<'info> { } impl<'info> InitServiceRegistry<'info> { - pub fn handler(&mut self, fee_account: Pubkey, fee_percentage: u8) -> Result<()> { + pub fn handler( + &mut self, + fee_account: Pubkey, + fee_token_account: Pubkey, + fee_percentage: u8, + ) -> Result<()> { self.service_registry.fee_account = fee_account; self.service_registry.fee_percentage = fee_percentage; + self.service_registry.fee_token_account = fee_token_account; msg!( - "Service Registry Initialized with fee account: {} and fee percentage: {}", + "Service Registry Initialized with fee account: {} and token account:{} and fee percentage: {}", fee_account, + fee_token_account, fee_percentage ); Ok(()) diff --git a/anchor/programs/gigentic/src/contexts/mod.rs b/anchor/programs/gigentic/src/contexts/mod.rs index 2309edb..7bc2387 100644 --- a/anchor/programs/gigentic/src/contexts/mod.rs +++ b/anchor/programs/gigentic/src/contexts/mod.rs @@ -2,5 +2,7 @@ pub mod customer_to_provider_rating; pub mod init_service; pub mod init_service_registry; pub mod pay_service; +pub mod pay_service_spl; pub mod provider_to_customer_rating; pub mod sign_service; +pub mod sign_service_spl; diff --git a/anchor/programs/gigentic/src/contexts/pay_service.rs b/anchor/programs/gigentic/src/contexts/pay_service.rs index 0101e98..ea26df0 100644 --- a/anchor/programs/gigentic/src/contexts/pay_service.rs +++ b/anchor/programs/gigentic/src/contexts/pay_service.rs @@ -32,7 +32,6 @@ pub struct PayService<'info> { bump, )] pub review: Account<'info, Review>, - pub system_program: Program<'info, System>, } @@ -55,6 +54,12 @@ impl<'info> PayService<'info> { ], )?; + self.service.reviews.push(self.review.key()); + if let Some(last_address) = self.service.reviews.last() { + msg!(" Last review address: {}", last_address); + } else { + return err!(ErrorCode::NoReviews); + } self.review.set_inner(Review { review_id, provider_to_customer_rating: 0, @@ -71,15 +76,11 @@ impl<'info> PayService<'info> { customer: self.customer.key(), service_provider: self.service.provider, expected_amount: service_price, + escrow_token_account: None, + fee_token_account: None, + service_provider_token_account: None, }); - self.service.reviews.push(self.review.key()); - if let Some(last_address) = self.service.reviews.last() { - msg!("Review added. Last address: {}", last_address); - } else { - return err!(ErrorCode::NoReviews); - } - Ok(()) } } diff --git a/anchor/programs/gigentic/src/contexts/pay_service_spl.rs b/anchor/programs/gigentic/src/contexts/pay_service_spl.rs new file mode 100644 index 0000000..d38da1c --- /dev/null +++ b/anchor/programs/gigentic/src/contexts/pay_service_spl.rs @@ -0,0 +1,113 @@ +use crate::states::review::Review; +use crate::states::service_registry::ServiceRegistry; +use crate::states::{Escrow, Service}; +use anchor_lang::prelude::*; +use anchor_spl::token::{self, Mint, Token, TokenAccount, Transfer}; + +/// Accounts required for the `PayServiceSPl` instruction. +#[derive(Accounts)] +#[instruction(review_id: String)] +pub struct PayServiceSpl<'info> { + /// The customer who will sign the transaction. + #[account(mut)] + pub customer: Signer<'info>, + + /// The service account. + #[account(mut)] + pub service: Box>, + + /// The service registry account. + #[account(mut)] + service_registry: Box>, + + /// The escrow account, initialized with a specific space and seeds. + #[account( + init, + payer = customer, + space = 8 + Escrow::INIT_SPACE, + seeds = [b"escrow", service.key().as_ref(), service.provider.key().as_ref(), customer.key().as_ref()], + bump + )] + pub escrow: Box>, + + #[account(mut)] + pub customer_token_account: Box>, + + /// The mint account. + pub mint: Account<'info, Mint>, + + /// The token account for the escrow, initialized with the mint and authority. + #[account( + init, + payer = customer, + token::mint = mint, + token::authority = escrow_token_account, + seeds = [b"escrow-token-account", escrow.key().as_ref()], + bump + )] + pub escrow_token_account: Box>, + + #[account( + init, + payer = customer, + space = 8 + Review::INIT_SPACE, + seeds = [b"review", review_id.as_bytes(), service.key().as_ref()], + bump, + )] + pub review: Account<'info, Review>, // Moved to heap + + /// The token program. + pub token_program: Program<'info, Token>, + + /// The rent sysvar. + pub rent: Sysvar<'info, Rent>, + + /// The system program. + pub system_program: Program<'info, System>, +} +impl<'info> PayServiceSpl<'info> { + pub fn handler(&mut self, review_id: String) -> Result<()> { + // Setting up escrow details + self.escrow.customer = self.customer.key(); + self.escrow.service_provider = self.service.provider; + self.escrow.fee_percentage = self.service_registry.fee_percentage; + self.escrow.expected_amount = self.service.price; + self.escrow.fee_account = self.service_registry.fee_account; + self.escrow.service_provider_token_account = + Some(self.service.service_provider_token_account); + self.escrow.fee_token_account = Some(self.escrow_token_account.key()); + self.escrow.escrow_token_account = Some(self.escrow_token_account.key()); + + // Sets the review details + self.review.set_inner(Review { + review_id, + provider_to_customer_rating: 0, + customer_to_provider_rating: 0, + customer: self.customer.key(), + service_provider: self.service.provider.key(), + provider_to_customer_review: String::from(""), + customer_to_provider_review: String::from(""), + }); + + self.service.reviews.push(self.review.key()); + + // Transfers spl tokens + self.transfer_spl_tokens(self.service.price)?; + + Ok(()) + } + fn transfer_spl_tokens(&self, amount: u64) -> Result<()> { + token::transfer( + CpiContext::new( + self.token_program.to_account_info(), + Transfer { + from: self.customer_token_account.to_account_info(), + to: self.escrow_token_account.to_account_info(), + authority: self.customer.to_account_info(), + }, + ), + amount, + )?; + Ok(()) + } +} diff --git a/anchor/programs/gigentic/src/contexts/provider_to_customer_rating.rs b/anchor/programs/gigentic/src/contexts/provider_to_customer_rating.rs index ee53b1e..6931a34 100644 --- a/anchor/programs/gigentic/src/contexts/provider_to_customer_rating.rs +++ b/anchor/programs/gigentic/src/contexts/provider_to_customer_rating.rs @@ -7,9 +7,9 @@ pub struct ReviewProviderToCustomerService<'info> { // The account of the user deploying and paying for the initialization. // Marked as `mut` because it will be charged for rent. #[account(mut)] - pub signer: Signer<'info>, + pub provider: Signer<'info>, - #[account(mut, constraint = review.service_provider == signer.key())] + #[account(mut, constraint = review.service_provider == provider.key())] pub review: Account<'info, Review>, pub system_program: Program<'info, System>, diff --git a/anchor/programs/gigentic/src/contexts/sign_service.rs b/anchor/programs/gigentic/src/contexts/sign_service.rs index fdb763e..eb7aa4b 100644 --- a/anchor/programs/gigentic/src/contexts/sign_service.rs +++ b/anchor/programs/gigentic/src/contexts/sign_service.rs @@ -5,24 +5,24 @@ use anchor_lang::prelude::*; #[derive(Accounts)] pub struct SignService<'info> { #[account(mut)] - pub signer: Signer<'info>, + pub customer: Signer<'info>, #[account(mut)] pub service: Account<'info, Service>, #[account( mut, - close = signer, // Transfer remaining lamports to the customer when the account is closed - seeds = [b"escrow", service.key().as_ref(), service.provider.key().as_ref(), signer.key().as_ref()], + close = customer, // Transfer remaining lamports to the customer when the account is closed + seeds = [b"escrow", service.key().as_ref(), service.provider.key().as_ref(), customer.key().as_ref()], bump, )] pub escrow: Account<'info, Escrow>, - /// CHECK : This is an account info, not an account + /// CHECK: This is an account info, not an account #[account(mut, constraint = service_provider.key() == escrow.service_provider.key() && service_provider.key() == service.provider.key())] pub service_provider: AccountInfo<'info>, - /// CHECK : SAFE + /// CHECK: SAFE #[account(mut, constraint = fee_account.key() == escrow.fee_account.key())] pub fee_account: AccountInfo<'info>, diff --git a/anchor/programs/gigentic/src/contexts/sign_service_spl.rs b/anchor/programs/gigentic/src/contexts/sign_service_spl.rs new file mode 100644 index 0000000..c7d4d8b --- /dev/null +++ b/anchor/programs/gigentic/src/contexts/sign_service_spl.rs @@ -0,0 +1,99 @@ +use crate::states::{Escrow, Service}; +use crate::ErrorCode; +use anchor_lang::prelude::*; +use anchor_spl::token::{self, Mint, Token, TokenAccount}; + +/// Accounts required for the `SignService` instruction. +#[derive(Accounts)] +pub struct SignServiceSpl<'info> { + #[account(mut)] + pub customer: Signer<'info>, + + pub service: Account<'info, Service>, + + #[account( + mut, + close = customer, // Transfer remaining lamports to the buyer when the account is closed + seeds = [b"escrow", service.key().as_ref(), service.provider.key().as_ref(), customer.key().as_ref()], + bump, + )] + pub escrow: Account<'info, Escrow>, + + /// CHECK: This account is safe to use. + #[account(mut)] + pub service_provider: AccountInfo<'info>, + + #[account( + mut, + constraint = fee_token_account.mint == mint.key() + )] + pub fee_token_account: Account<'info, TokenAccount>, + + #[account(mut)] + pub service_provider_token_account: Account<'info, TokenAccount>, + + pub mint: Account<'info, Mint>, + + #[account( + mut, + seeds = [b"escrow-token-account", escrow.key().as_ref()], + bump, + )] + pub escrow_token_account: Account<'info, TokenAccount>, // The escrow token account + + pub token_program: Program<'info, Token>, + + pub system_program: Program<'info, System>, +} + +impl<'info> SignServiceSpl<'info> { + pub fn handler(&mut self, bump: &u8) -> Result<()> { + let escrow = &self.escrow; + let amount = escrow.expected_amount; + let fee_percentage = escrow.fee_percentage; + + // Calculate fee and amount after fee + let fee: u64 = amount + .checked_mul(fee_percentage as u64) + .ok_or(ErrorCode::Overflow)? + .checked_div(100) + .ok_or(ErrorCode::Overflow)?; + + let amount_after_fee = amount.checked_sub(fee).ok_or(ErrorCode::Overflow)?; + let escrow_key = self.escrow.key(); + let seeds = &[ + b"escrow-token-account".as_ref(), + escrow_key.as_ref(), + &[*bump], + ]; + let signer = [&seeds[..]]; + + // Transfer amount after fee to service provider + let service_provider_ctx = CpiContext::new_with_signer( + self.token_program.to_account_info(), + token::Transfer { + from: self.escrow_token_account.to_account_info(), + authority: self.escrow_token_account.to_account_info(), + to: self.service_provider_token_account.to_account_info(), + }, + &signer, + ); + token::transfer(service_provider_ctx, amount_after_fee)?; + + // Transfer fee to fee account if non-zero + if fee > 0 { + let fee_ctx = CpiContext::new_with_signer( + self.token_program.to_account_info(), + token::Transfer { + from: self.escrow_token_account.to_account_info(), + authority: self.escrow_token_account.to_account_info(), + to: self.fee_token_account.to_account_info(), + }, + &signer, + ); + token::transfer(fee_ctx, fee)?; + } + + Ok(()) + } +} diff --git a/anchor/programs/gigentic/src/lib.rs b/anchor/programs/gigentic/src/lib.rs index 422c1ed..9aea537 100644 --- a/anchor/programs/gigentic/src/lib.rs +++ b/anchor/programs/gigentic/src/lib.rs @@ -7,22 +7,27 @@ use contexts::customer_to_provider_rating::*; use contexts::init_service::*; use contexts::init_service_registry::*; use contexts::pay_service::*; +use contexts::pay_service_spl::*; use contexts::provider_to_customer_rating::*; use contexts::sign_service::*; +use contexts::sign_service_spl::*; use errors::ErrorCode; declare_id!("2xtwCiDhiQ9vuTFpR3wECJaHyvtE7L9pBPbNHdnsk1YS"); #[program] pub mod gigentic { + use super::*; pub fn initialize_service_registry( ctx: Context, fee_account: Pubkey, + fee_token_account: Pubkey, fee_percentage: u8, ) -> Result<()> { - ctx.accounts.handler(fee_account, fee_percentage)?; + ctx.accounts + .handler(fee_account, fee_token_account, fee_percentage)?; Ok(()) } @@ -68,4 +73,15 @@ pub mod gigentic { ctx.accounts.handler(rating, review)?; Ok(()) } + + pub fn pay_service_spl(ctx: Context, review_id: String) -> Result<()> { + ctx.accounts.handler(review_id)?; + Ok(()) + } + + pub fn sign_service_spl(ctx: Context) -> Result<()> { + let bump = &ctx.bumps.escrow_token_account; + ctx.accounts.handler(bump)?; + Ok(()) + } } diff --git a/anchor/programs/gigentic/src/states/escrow.rs b/anchor/programs/gigentic/src/states/escrow.rs index 97eb48d..e0868cc 100644 --- a/anchor/programs/gigentic/src/states/escrow.rs +++ b/anchor/programs/gigentic/src/states/escrow.rs @@ -3,9 +3,12 @@ use anchor_lang::prelude::*; #[account] #[derive(InitSpace)] pub struct Escrow { - pub customer: Pubkey, // the customer who will pay the money to the escrow - pub service_provider: Pubkey, // the service provider who will receive the money from the escrow - pub fee_percentage: u8, // the fee percentage that the service provider will pay to the registry - pub expected_amount: u64, // the expected amount for the service - pub fee_account: Pubkey, // the fee account that will receive the fee from the service provider + pub customer: Pubkey, // what this escrow is for + pub service_provider: Pubkey, // the service provider for who is money getting transferred to + pub fee_percentage: u8, // The fee% + pub expected_amount: u64, + pub fee_account: Pubkey, + pub fee_token_account: Option, + pub service_provider_token_account: Option, + pub escrow_token_account: Option, } diff --git a/anchor/programs/gigentic/src/states/service.rs b/anchor/programs/gigentic/src/states/service.rs index 0f3e3a6..a94056d 100644 --- a/anchor/programs/gigentic/src/states/service.rs +++ b/anchor/programs/gigentic/src/states/service.rs @@ -11,4 +11,5 @@ pub struct Service { pub price: u64, #[max_len(MAX_REVIEWS)] pub reviews: Vec, + pub service_provider_token_account: Pubkey, } diff --git a/anchor/programs/gigentic/src/states/service_registry.rs b/anchor/programs/gigentic/src/states/service_registry.rs index 79998e7..3b161a3 100644 --- a/anchor/programs/gigentic/src/states/service_registry.rs +++ b/anchor/programs/gigentic/src/states/service_registry.rs @@ -9,4 +9,5 @@ pub struct ServiceRegistry { pub service_account_addresses: Vec, pub fee_account: Pubkey, pub fee_percentage: u8, + pub fee_token_account: Pubkey, } diff --git a/anchor/target/idl/gigentic.json b/anchor/target/idl/gigentic.json index 5cd1051..64e9281 100644 --- a/anchor/target/idl/gigentic.json +++ b/anchor/target/idl/gigentic.json @@ -1,5 +1,5 @@ { - "address": "2xtwCiDhiQ9vuTFpR3wECJaHyvtE7L9pBPbNHdnsk1YS", + "address": "FBXJXb1DnGsFzea4iXSFxg2ztTpENCGQ5TXGQbr4WBB", "metadata": { "name": "gigentic", "version": "0.1.0", @@ -12,7 +12,7 @@ "discriminator": [188, 220, 123, 11, 148, 57, 198, 128], "accounts": [ { - "name": "signer", + "name": "customer", "writable": true, "signer": true }, @@ -69,6 +69,28 @@ ] } }, + { + "name": "service_provider_token_account" + }, + { + "name": "service_authority", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, 101, 114, 118, 105, 99, 101, 95, 97, 117, 116, 104, 111, + 114, 105, 116, 121 + ] + }, + { + "kind": "account", + "path": "service" + } + ] + } + }, { "name": "mint" }, @@ -127,6 +149,10 @@ "name": "fee_account", "type": "pubkey" }, + { + "name": "fee_token_account", + "type": "pubkey" + }, { "name": "fee_percentage", "type": "u8" @@ -207,12 +233,133 @@ } ] }, + { + "name": "pay_service_spl", + "discriminator": [170, 1, 4, 226, 23, 248, 125, 227], + "accounts": [ + { + "name": "customer", + "docs": ["The customer who will sign the transaction."], + "writable": true, + "signer": true + }, + { + "name": "service", + "docs": ["The service account."], + "writable": true + }, + { + "name": "service_registry", + "docs": ["The service registry account."], + "writable": true + }, + { + "name": "escrow", + "docs": [ + "The escrow account, initialized with a specific space and seeds." + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [101, 115, 99, 114, 111, 119] + }, + { + "kind": "account", + "path": "service" + }, + { + "kind": "account", + "path": "service.provider", + "account": "Service" + }, + { + "kind": "account", + "path": "customer" + } + ] + } + }, + { + "name": "customer_token_account", + "writable": true + }, + { + "name": "mint", + "docs": ["The mint account."] + }, + { + "name": "escrow_token_account", + "docs": [ + "The token account for the escrow, initialized with the mint and authority." + ], + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 101, 115, 99, 114, 111, 119, 45, 116, 111, 107, 101, 110, 45, + 97, 99, 99, 111, 117, 110, 116 + ] + }, + { + "kind": "account", + "path": "escrow" + } + ] + } + }, + { + "name": "review", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [114, 101, 118, 105, 101, 119] + }, + { + "kind": "arg", + "path": "review_id" + }, + { + "kind": "account", + "path": "service" + } + ] + } + }, + { + "name": "token_program", + "docs": ["The token program."], + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "rent", + "docs": ["The rent sysvar."], + "address": "SysvarRent111111111111111111111111111111111" + }, + { + "name": "system_program", + "docs": ["The system program."], + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "review_id", + "type": "string" + } + ] + }, { "name": "provider_to_customer_rating", "discriminator": [107, 198, 87, 138, 229, 212, 60, 70], "accounts": [ { - "name": "signer", + "name": "provider", "writable": true, "signer": true }, @@ -241,7 +388,7 @@ "discriminator": [170, 73, 190, 114, 213, 177, 176, 218], "accounts": [ { - "name": "signer", + "name": "customer", "writable": true, "signer": true }, @@ -269,19 +416,17 @@ }, { "kind": "account", - "path": "signer" + "path": "customer" } ] } }, { "name": "service_provider", - "docs": ["CHECK : This is an account info, not an account"], "writable": true }, { "name": "fee_account", - "docs": ["CHECK : SAFE"], "writable": true }, { @@ -290,6 +435,88 @@ } ], "args": [] + }, + { + "name": "sign_service_spl", + "discriminator": [31, 15, 93, 60, 8, 175, 224, 119], + "accounts": [ + { + "name": "customer", + "writable": true, + "signer": true + }, + { + "name": "service" + }, + { + "name": "escrow", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [101, 115, 99, 114, 111, 119] + }, + { + "kind": "account", + "path": "service" + }, + { + "kind": "account", + "path": "service.provider", + "account": "Service" + }, + { + "kind": "account", + "path": "customer" + } + ] + } + }, + { + "name": "service_provider", + "writable": true + }, + { + "name": "fee_token_account", + "writable": true + }, + { + "name": "service_provider_token_account", + "writable": true + }, + { + "name": "mint" + }, + { + "name": "escrow_token_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 101, 115, 99, 114, 111, 119, 45, 116, 111, 107, 101, 110, 45, + 97, 99, 99, 111, 117, 110, 116 + ] + }, + { + "kind": "account", + "path": "escrow" + } + ] + } + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] } ], "accounts": [ @@ -305,6 +532,10 @@ "name": "Service", "discriminator": [144, 62, 76, 129, 167, 36, 151, 250] }, + { + "name": "ServiceAuthority", + "discriminator": [199, 242, 58, 222, 53, 161, 60, 220] + }, { "name": "ServiceRegistry", "discriminator": [105, 133, 96, 79, 207, 176, 202, 71] @@ -392,6 +623,24 @@ { "name": "fee_account", "type": "pubkey" + }, + { + "name": "fee_token_account", + "type": { + "option": "pubkey" + } + }, + { + "name": "service_provider_token_account", + "type": { + "option": "pubkey" + } + }, + { + "name": "escrow_token_account", + "type": { + "option": "pubkey" + } } ] } @@ -458,10 +707,21 @@ "type": { "vec": "pubkey" } + }, + { + "name": "service_provider_token_account", + "type": "pubkey" } ] } }, + { + "name": "ServiceAuthority", + "type": { + "kind": "struct", + "fields": [] + } + }, { "name": "ServiceRegistry", "docs": [ @@ -484,6 +744,10 @@ { "name": "fee_percentage", "type": "u8" + }, + { + "name": "fee_token_account", + "type": "pubkey" } ] } diff --git a/anchor/target/types/gigentic.ts b/anchor/target/types/gigentic.ts index 17ec399..10078eb 100644 --- a/anchor/target/types/gigentic.ts +++ b/anchor/target/types/gigentic.ts @@ -18,7 +18,7 @@ export type Gigentic = { discriminator: [188, 220, 123, 11, 148, 57, 198, 128]; accounts: [ { - name: 'signer'; + name: 'customer'; writable: true; signer: true; }, @@ -75,6 +75,43 @@ export type Gigentic = { ]; }; }, + { + name: 'serviceProviderTokenAccount'; + }, + { + name: 'serviceAuthority'; + writable: true; + pda: { + seeds: [ + { + kind: 'const'; + value: [ + 115, + 101, + 114, + 118, + 105, + 99, + 101, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121, + ]; + }, + { + kind: 'account'; + path: 'service'; + }, + ]; + }; + }, { name: 'mint'; }, @@ -133,6 +170,10 @@ export type Gigentic = { name: 'feeAccount'; type: 'pubkey'; }, + { + name: 'feeTokenAccount'; + type: 'pubkey'; + }, { name: 'feePercentage'; type: 'u8'; @@ -213,12 +254,151 @@ export type Gigentic = { }, ]; }, + { + name: 'payServiceSpl'; + discriminator: [170, 1, 4, 226, 23, 248, 125, 227]; + accounts: [ + { + name: 'customer'; + docs: ['The customer who will sign the transaction.']; + writable: true; + signer: true; + }, + { + name: 'service'; + docs: ['The service account.']; + writable: true; + }, + { + name: 'serviceRegistry'; + docs: ['The service registry account.']; + writable: true; + }, + { + name: 'escrow'; + docs: [ + 'The escrow account, initialized with a specific space and seeds.', + ]; + writable: true; + pda: { + seeds: [ + { + kind: 'const'; + value: [101, 115, 99, 114, 111, 119]; + }, + { + kind: 'account'; + path: 'service'; + }, + { + kind: 'account'; + path: 'service.provider'; + account: 'service'; + }, + { + kind: 'account'; + path: 'customer'; + }, + ]; + }; + }, + { + name: 'customerTokenAccount'; + writable: true; + }, + { + name: 'mint'; + docs: ['The mint account.']; + }, + { + name: 'escrowTokenAccount'; + docs: [ + 'The token account for the escrow, initialized with the mint and authority.', + ]; + writable: true; + pda: { + seeds: [ + { + kind: 'const'; + value: [ + 101, + 115, + 99, + 114, + 111, + 119, + 45, + 116, + 111, + 107, + 101, + 110, + 45, + 97, + 99, + 99, + 111, + 117, + 110, + 116, + ]; + }, + { + kind: 'account'; + path: 'escrow'; + }, + ]; + }; + }, + { + name: 'review'; + writable: true; + pda: { + seeds: [ + { + kind: 'const'; + value: [114, 101, 118, 105, 101, 119]; + }, + { + kind: 'arg'; + path: 'reviewId'; + }, + { + kind: 'account'; + path: 'service'; + }, + ]; + }; + }, + { + name: 'tokenProgram'; + docs: ['The token program.']; + address: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'; + }, + { + name: 'rent'; + docs: ['The rent sysvar.']; + address: 'SysvarRent111111111111111111111111111111111'; + }, + { + name: 'systemProgram'; + docs: ['The system program.']; + address: '11111111111111111111111111111111'; + }, + ]; + args: [ + { + name: 'reviewId'; + type: 'string'; + }, + ]; + }, { name: 'providerToCustomerRating'; discriminator: [107, 198, 87, 138, 229, 212, 60, 70]; accounts: [ { - name: 'signer'; + name: 'provider'; writable: true; signer: true; }, @@ -247,7 +427,7 @@ export type Gigentic = { discriminator: [170, 73, 190, 114, 213, 177, 176, 218]; accounts: [ { - name: 'signer'; + name: 'customer'; writable: true; signer: true; }, @@ -275,19 +455,17 @@ export type Gigentic = { }, { kind: 'account'; - path: 'signer'; + path: 'customer'; }, ]; }; }, { name: 'serviceProvider'; - docs: ['CHECK : This is an account info, not an account']; writable: true; }, { name: 'feeAccount'; - docs: ['CHECK : SAFE']; writable: true; }, { @@ -297,6 +475,106 @@ export type Gigentic = { ]; args: []; }, + { + name: 'signServiceSpl'; + discriminator: [31, 15, 93, 60, 8, 175, 224, 119]; + accounts: [ + { + name: 'customer'; + writable: true; + signer: true; + }, + { + name: 'service'; + }, + { + name: 'escrow'; + writable: true; + pda: { + seeds: [ + { + kind: 'const'; + value: [101, 115, 99, 114, 111, 119]; + }, + { + kind: 'account'; + path: 'service'; + }, + { + kind: 'account'; + path: 'service.provider'; + account: 'service'; + }, + { + kind: 'account'; + path: 'customer'; + }, + ]; + }; + }, + { + name: 'serviceProvider'; + writable: true; + }, + { + name: 'feeTokenAccount'; + writable: true; + }, + { + name: 'serviceProviderTokenAccount'; + writable: true; + }, + { + name: 'mint'; + }, + { + name: 'escrowTokenAccount'; + writable: true; + pda: { + seeds: [ + { + kind: 'const'; + value: [ + 101, + 115, + 99, + 114, + 111, + 119, + 45, + 116, + 111, + 107, + 101, + 110, + 45, + 97, + 99, + 99, + 111, + 117, + 110, + 116, + ]; + }, + { + kind: 'account'; + path: 'escrow'; + }, + ]; + }; + }, + { + name: 'tokenProgram'; + address: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'; + }, + { + name: 'systemProgram'; + address: '11111111111111111111111111111111'; + }, + ]; + args: []; + }, ]; accounts: [ { @@ -311,6 +589,10 @@ export type Gigentic = { name: 'service'; discriminator: [144, 62, 76, 129, 167, 36, 151, 250]; }, + { + name: 'serviceAuthority'; + discriminator: [199, 242, 58, 222, 53, 161, 60, 220]; + }, { name: 'serviceRegistry'; discriminator: [105, 133, 96, 79, 207, 176, 202, 71]; @@ -399,6 +681,24 @@ export type Gigentic = { name: 'feeAccount'; type: 'pubkey'; }, + { + name: 'feeTokenAccount'; + type: { + option: 'pubkey'; + }; + }, + { + name: 'serviceProviderTokenAccount'; + type: { + option: 'pubkey'; + }; + }, + { + name: 'escrowTokenAccount'; + type: { + option: 'pubkey'; + }; + }, ]; }; }, @@ -465,9 +765,20 @@ export type Gigentic = { vec: 'pubkey'; }; }, + { + name: 'serviceProviderTokenAccount'; + type: 'pubkey'; + }, ]; }; }, + { + name: 'serviceAuthority'; + type: { + kind: 'struct'; + fields: []; + }; + }, { name: 'serviceRegistry'; docs: [ @@ -491,6 +802,10 @@ export type Gigentic = { name: 'feePercentage'; type: 'u8'; }, + { + name: 'feeTokenAccount'; + type: 'pubkey'; + }, ]; }; }, diff --git a/anchor/tests/constants.ts b/anchor/tests/constants.ts index 5e14612..43b135a 100644 --- a/anchor/tests/constants.ts +++ b/anchor/tests/constants.ts @@ -1,8 +1,9 @@ import { AnchorProvider } from '@coral-xyz/anchor'; import { LAMPORTS_PER_SOL } from '@solana/web3.js'; -import { Keypair } from '@solana/web3.js'; +import { Keypair, PublicKey } from '@solana/web3.js'; export const REVIEW_ID = '1'; +export const REVIEW_ID_2 = '2'; export const PROVIDER = AnchorProvider.env(); export const SERVICE_REGISTRY_SPACE = 10_000_000; export const SERVICE_REGISTRY_SPACE_SMALL = 1000; @@ -14,10 +15,11 @@ export const TEST_FEE_ACCOUNT = Keypair.generate(); export const FEE_PERCENTAGE = 1; export const AIRDROP_SOL_AMOUNT = 1000; // Amount in SOL export const AIRDROP_LAMPORTS = AIRDROP_SOL_AMOUNT * LAMPORTS_PER_SOL; +export let TOKEN_MINT: PublicKey; // KEYPAIRS // export const REGISTRY_KEYPAIR = Keypair.generate(); -export const MINT_AUTHORITY: Keypair = Keypair.generate(); +export const MINT_AUTHORITY_KEYPAIR: Keypair = Keypair.generate(); // SERVICE DEPLOYERS export const TEST_SERVICE_DEPLOYERS: Keypair[] = [ @@ -31,6 +33,3 @@ export const TEST_SERVICE_USERS: Keypair[] = [ Keypair.generate(), Keypair.generate(), ]; - -// SEEDS -// export const SOME_SEED: string = "some-registry"; diff --git a/anchor/tests/customer_to_provider_rating.ts b/anchor/tests/customer_to_provider_rating.ts index 9de1ba7..3164abc 100644 --- a/anchor/tests/customer_to_provider_rating.ts +++ b/anchor/tests/customer_to_provider_rating.ts @@ -7,7 +7,7 @@ import { expect } from 'chai'; import { TEST_SERVICE_DEPLOYERS, TEST_SERVICE_USERS } from './constants'; describe('Customer to provider review', () => { - it('Gives the service review to the customer and checks if the review has the values assigned', async () => { + it('should assign a review and validate the values for review number 1', async () => { // Select the customer from the predefined list of service users // The customer will be reviewing the service provided by the provider const customer = TEST_SERVICE_USERS[0]; @@ -47,7 +47,7 @@ describe('Customer to provider review', () => { await program.methods .customerToProviderRating(rating, review) .accounts({ - signer: customer.publicKey, + customer: customer.publicKey, review: serviceAccount.reviews[0], }) .signers([customer]) @@ -92,4 +92,92 @@ describe('Customer to provider review', () => { 'The review comment given by the customer should match the comment stored in the review account.', ); }); + + it('should assign a review and validate the values for review number 2', async () => { + // Select the customer from the predefined list of service users + // The customer will be reviewing the service provided by the provider + + // Second service was used by the second customer + const customer = TEST_SERVICE_USERS[1]; + + // Fund the customer's account with enough SOL to pay transaction fees + await fund_account(connection, customer.publicKey); + + // Check the balance of the customer's account to ensure it has sufficient SOL for fees + const customerBalance = await connection.getBalance(customer.publicKey); + + // Verify that the customer has at least 0.01 SOL in their account (for transaction fees) + if (customerBalance < 0.01 * anchor.web3.LAMPORTS_PER_SOL) { + throw new Error( + 'customer does not have enough SOL to pay transaction fees.', + ); + } + + // Fetch the service registry account using the program and its public key. + // The service registry holds references to the services deployed by providers. + const serviceRegistry = await program.account.serviceRegistry.fetch( + TEST_SERVICE_REGISTRY_KEYPAIR.publicKey, + ); + + // Retrieve the public key of the first service account from the service registry + // This service account holds information about the service provided by the provider. + const serviceAccountPubKey = serviceRegistry.serviceAccountAddresses[0]; + + // Fetch the service account details using the service account public key + const serviceAccount = + await program.account.service.fetch(serviceAccountPubKey); + + // Define the rating (out of 5) and the review for the service provider + const rating = 5; + const review = 'Great service'; + + try { + await program.methods + .customerToProviderRating(rating, review) + .accounts({ + customer: customer.publicKey, + review: serviceAccount.reviews[1], // use the second review account + }) + .signers([customer]) + .rpc(); + } catch (err) { + // Handle transaction errors + if (err instanceof SendTransactionError) { + console.error('SendTransactionError:', err.message); + } + throw err; // Re-throw the error to ensure the test fails + } + + // Find the program address for the review account. + // The review account stores the review and rating data linked to the service account. + + // Fetch the review account details using the generated program address + const reviewAccount = await program.account.review.fetch( + serviceAccount.reviews[1], // @ // use the second review account + ); + + // Validate that the service provider stored in the review account matches the expected service provider + expect(reviewAccount.serviceProvider.toBase58()).to.equal( + TEST_SERVICE_DEPLOYERS[0].publicKey.toBase58(), + 'The service provider in the review account should match the service provider who owns the service.', + ); + + // Validate that the customer (customer) stored in the review account matches the customer who submitted the review + expect(reviewAccount.customer.toBase58()).to.equal( + customer.publicKey.toBase58(), + 'The customer in the review account should match the customer who submitted the review.', + ); + + // Validate that the rating given by the customer matches the rating stored in the review account + expect(reviewAccount.customerToProviderRating).to.equal( + rating, + 'The rating given by the customer should match the rating stored in the review account.', + ); + + // Validate that the review comment matches the comment stored in the review account + expect(reviewAccount.customerToProviderReview).to.equal( + review, + 'The review comment given by the customer should match the comment stored in the review account.', + ); + }); }); diff --git a/anchor/tests/gigentic.spec.ts b/anchor/tests/gigentic.spec.ts index 1837d4d..1014d41 100644 --- a/anchor/tests/gigentic.spec.ts +++ b/anchor/tests/gigentic.spec.ts @@ -3,5 +3,7 @@ import './init_service_registry'; import './init_service'; import './pay_service'; import './sign_service'; +import './pay_service_spl'; +import './sign_service_spl'; import './customer_to_provider_rating'; import './provider_to_customer_rating'; diff --git a/anchor/tests/init.ts b/anchor/tests/init.ts index 7e61ac5..16df545 100644 --- a/anchor/tests/init.ts +++ b/anchor/tests/init.ts @@ -2,15 +2,21 @@ import { before } from 'mocha'; import { TEST_SERVICE_REGISTRY_DEPLOYER_KEYPAIR, - MINT_AUTHORITY, + MINT_AUTHORITY_KEYPAIR, PROVIDER, TEST_SERVICE_DEPLOYERS, TEST_FEE_ACCOUNT, + TEST_SERVICE_USERS, } from './constants'; import { fund_account } from './utils'; import * as anchor from '@coral-xyz/anchor'; -import { createMint } from '@solana/spl-token'; +import { + createMint, + mintTo, + getAccount, + createAccount, +} from '@solana/spl-token'; import { Program, web3 } from '@coral-xyz/anchor'; import { PublicKey } from '@solana/web3.js'; import { Gigentic } from '../target/types/gigentic'; @@ -27,7 +33,9 @@ export const program: Program = anchor.workspace // Declare a variable to hold the mint public key export let mint: PublicKey; - +export let feeTokenAccount: PublicKey; +export let serviceProviderTokenAccount: PublicKey; +export let customerTokenAccount: PublicKey; /** * This block will run before every test in every test file. * It ensures that necessary accounts are funded and a new mint is created. @@ -36,22 +44,58 @@ before(async () => { // Fund the TEST_SERVICE_REGISTRY_DEPLOYER_KEYPAIR, MINT_AUTHORITY, and SERVICE_DEPLOYERS accounts with SOL const fundingPromises = [ fund_account(connection, TEST_SERVICE_REGISTRY_DEPLOYER_KEYPAIR.publicKey), - fund_account(connection, MINT_AUTHORITY.publicKey), + fund_account(connection, MINT_AUTHORITY_KEYPAIR.publicKey), fund_account(connection, TEST_FEE_ACCOUNT.publicKey), ...TEST_SERVICE_DEPLOYERS.map((deployer) => fund_account(connection, deployer.publicKey), ), + ...TEST_SERVICE_USERS.map((user) => + fund_account(connection, user.publicKey), + ), ]; // Wait for all funding promises to complete in parallel await Promise.all(fundingPromises); - // Create a new SPL token mint with 8 decimal places - mint = await createMint( - connection, - MINT_AUTHORITY, // Fee payer for the mint creation - MINT_AUTHORITY.publicKey, // Mint authority that can mint new tokens - MINT_AUTHORITY.publicKey, // Freeze authority (can be set to `null` to disable freezing) - 8, // Number of decimals for the mint (similar to a currency's smallest unit) - ); + try { + // Create a new SPL token mint with 8 decimal places + mint = await createMint( + connection, + MINT_AUTHORITY_KEYPAIR, // Fee payer for the mint creation + MINT_AUTHORITY_KEYPAIR.publicKey, // Mint authority that can mint new tokens + MINT_AUTHORITY_KEYPAIR.publicKey, // Freeze authority (can be set to `null` to disable freezing) + 8, // Number of decimals for the mint (similar to a currency's smallest unit) + ); + feeTokenAccount = await createAccount( + connection, + TEST_FEE_ACCOUNT, // Payer + mint, // Mint + TEST_FEE_ACCOUNT.publicKey, // Owner + ); + + serviceProviderTokenAccount = await createAccount( + connection, + TEST_SERVICE_DEPLOYERS[0], // Payer + mint, // Mint + TEST_SERVICE_DEPLOYERS[0].publicKey, // Owner + ); + customerTokenAccount = await createAccount( + connection, + TEST_SERVICE_USERS[1], // Payer + mint, // Mint + TEST_SERVICE_USERS[1].publicKey, // Owner + ); + + // Mint tokens to the customer's token account + await mintTo( + connection, + MINT_AUTHORITY_KEYPAIR, // Payer + mint, // Mint + customerTokenAccount, // Destination + MINT_AUTHORITY_KEYPAIR, // Authority + 1000000000, // Amount + ); + } catch (err) { + console.error('Error during token minting and account creation:', err); + } }); diff --git a/anchor/tests/init_service.ts b/anchor/tests/init_service.ts index c26ad63..cb88f8f 100644 --- a/anchor/tests/init_service.ts +++ b/anchor/tests/init_service.ts @@ -4,7 +4,8 @@ import { TEST_SERVICE_DEPLOYERS, TEST_SERVICE_REGISTRY_KEYPAIR, } from './constants'; -import { program, mint } from './init'; +import { program } from './init'; +import { mint, serviceProviderTokenAccount } from './init'; import { TOKEN_PROGRAM_ID } from '@solana/spl-token'; describe('Gigentic Service Deployment', () => { @@ -16,25 +17,23 @@ describe('Gigentic Service Deployment', () => { // const uniqueId = 'service_' + Math.random().toString(36).substring(2, 15); const uniqueId = '1'; - const description = 'Test description h'; + const description = 'Test description '; const price = new anchor.BN(1000); try { // Fetch the public key of the deployer const deployerPublicKey = TEST_SERVICE_DEPLOYERS[deployerIndex].publicKey; - - // Deploy a new service to the service registry - // - Initialize a new service by calling the smart contract's method await program.methods .initializeService(uniqueId, description, price) .accounts({ - provider: deployerPublicKey, // Deployer account that provides the service - serviceRegistry: TEST_SERVICE_REGISTRY_KEYPAIR.publicKey, // The service registry account where the service will be registered - mint: mint, // Mint account for SPL token-based transactions - tokenProgram: TOKEN_PROGRAM_ID, // SPL Token Program ID for handling token transactions + provider: deployerPublicKey, + serviceRegistry: TEST_SERVICE_REGISTRY_KEYPAIR.publicKey, + mint: mint, + serviceProviderTokenAccount: serviceProviderTokenAccount, + tokenProgram: TOKEN_PROGRAM_ID, }) - .signers([TEST_SERVICE_DEPLOYERS[deployerIndex]]) // Sign the transaction with the deployer's keypair - .rpc(); // Execute the remote procedure call to interact with the blockchain + .signers([TEST_SERVICE_DEPLOYERS[deployerIndex]]) + .rpc(); } catch (error) { console.error('Failed to initialize service:', error); // Log an error message if service initialization fails throw error; // Re-throw the error to fail the test @@ -77,15 +76,16 @@ describe('Gigentic Service Deployment', () => { // Initialize a new service by calling the smart contract's method await program.methods - .initializeService(uniqueId, description, price) // Method to initialize a new service + .initializeService(uniqueId, description, price) .accounts({ - provider: deployerPublicKey, // Deployer account that provides the service - serviceRegistry: TEST_SERVICE_REGISTRY_KEYPAIR.publicKey, // The service registry account where the service will be registered - mint: mint, // Mint account for token-based transactions - tokenProgram: TOKEN_PROGRAM_ID, // SPL Token Program ID for handling token transactions + provider: deployerPublicKey, + serviceRegistry: TEST_SERVICE_REGISTRY_KEYPAIR.publicKey, + mint: mint, + serviceProviderTokenAccount: serviceProviderTokenAccount, + tokenProgram: TOKEN_PROGRAM_ID, }) - .signers([TEST_SERVICE_DEPLOYERS[deployerIndex]]) // Sign the transaction with the deployer's keypair - .rpc(); // Execute the remote procedure call to interact with the blockchain + .signers([TEST_SERVICE_DEPLOYERS[deployerIndex]]) + .rpc(); } catch (error) { console.error('Failed to initialize service:', error); // Log an error message if service initialization fails } diff --git a/anchor/tests/init_service_registry.ts b/anchor/tests/init_service_registry.ts index 3ea642f..d7097de 100644 --- a/anchor/tests/init_service_registry.ts +++ b/anchor/tests/init_service_registry.ts @@ -1,9 +1,9 @@ import { expect } from 'chai'; -import { before } from 'mocha'; import { SystemProgram, Transaction, sendAndConfirmTransaction, + PublicKey, } from '@solana/web3.js'; import { connection, program } from './init'; import { @@ -12,12 +12,25 @@ import { TEST_FEE_ACCOUNT, SERVICE_REGISTRY_SPACE, FEE_PERCENTAGE, + TEST_SERVICE_DEPLOYERS, + TEST_SERVICE_USERS, } from './constants'; +import { getAccount } from '@solana/spl-token'; +import { fund_account } from './utils'; +import { feeTokenAccount, customerTokenAccount } from './init'; -describe('Initialize Service Registry and checks for correct fee_account and correct fee percentage ', () => { +describe('Initialize Service Registry and checks for correct fee account and correct fee percentage', () => { before(async function () { + // Fund necessary accounts + await fund_account( + connection, + TEST_SERVICE_REGISTRY_DEPLOYER_KEYPAIR.publicKey, + ); + await fund_account(connection, TEST_SERVICE_DEPLOYERS[0].publicKey); + await fund_account(connection, TEST_SERVICE_USERS[0].publicKey); + await fund_account(connection, TEST_FEE_ACCOUNT.publicKey); + // Calculate the minimum balance required for rent exemption for an account of a given size. - // This prevents the account from being deleted due to insufficient balance. const rentExemptionAmount = await connection.getMinimumBalanceForRentExemption( SERVICE_REGISTRY_SPACE, @@ -45,10 +58,14 @@ describe('Initialize Service Registry and checks for correct fee_account and cor ]); }); - it('initializes a service registry', async () => { + it('Initializes a service registry', async () => { // Call the 'initializeServiceRegistry' method on the program to initialize the service registry account. await program.methods - .initializeServiceRegistry(TEST_FEE_ACCOUNT.publicKey, FEE_PERCENTAGE) // sets the fee_Account owner to the deployer, and for now sets the initial fee to 0 + .initializeServiceRegistry( + TEST_FEE_ACCOUNT.publicKey, + feeTokenAccount, + FEE_PERCENTAGE, + ) .accounts({ initializer: TEST_SERVICE_REGISTRY_DEPLOYER_KEYPAIR.publicKey, // Account that initializes the registry serviceRegistry: TEST_SERVICE_REGISTRY_KEYPAIR.publicKey, // The new service registry account being initialized @@ -72,6 +89,9 @@ describe('Initialize Service Registry and checks for correct fee_account and cor // Getting the actual Fee percentage const actualFeePercentage = fetchedRegistryAccount.feePercentage; + // Getting the actual fee token account + const actualFeeTokenAccount = fetchedRegistryAccount.feeTokenAccount; + // Verify that the actual service account addresses match the expected initial state. expect( actualServiceAccountAddresses, @@ -83,7 +103,13 @@ describe('Initialize Service Registry and checks for correct fee_account and cor TEST_FEE_ACCOUNT.publicKey.toBase58(), ); - // verify that the actual fee percentage matches the expected fee percentage + // Verify that the actual fee token account matches the expected fee token account + expect( + actualFeeTokenAccount.toBase58(), + 'Fee token account does not match', + ).to.equal(feeTokenAccount.toBase58()); + + // Verify that the actual fee percentage matches the expected fee percentage expect(actualFeePercentage, 'Fee percentage does not match').to.equal( FEE_PERCENTAGE, ); @@ -93,5 +119,22 @@ describe('Initialize Service Registry and checks for correct fee_account and cor actualServiceAccountAddresses.length, 'Service registry length does not match', ).to.equal(expectedServiceAccountAddresses.length); + + // Fetch the token balance of the buyerTokenAccount + const buyerTokenAccountInfo = await getAccount( + connection, + customerTokenAccount, + ); + + // Verify that the buyerTokenAccount has the expected token balance + const expectedTokenBalance = 1000000000; // Adjust the expected amount as needed + const actualTokenBalance = buyerTokenAccountInfo.amount; + + expect( + actualTokenBalance.toString(), + 'Buyer token account balance does not match', + ).to.equal(expectedTokenBalance.toString()); }); }); + +// Export the variables diff --git a/anchor/tests/pay_service_spl.ts b/anchor/tests/pay_service_spl.ts new file mode 100644 index 0000000..c9fc986 --- /dev/null +++ b/anchor/tests/pay_service_spl.ts @@ -0,0 +1,149 @@ +import * as anchor from '@coral-xyz/anchor'; +import { PublicKey } from '@solana/web3.js'; +import { expect } from 'chai'; +import { program, connection } from './init'; +import { + TEST_SERVICE_REGISTRY_KEYPAIR, + TEST_SERVICE_DEPLOYERS, + TEST_SERVICE_USERS, +} from './constants'; +import { customerTokenAccount, mint } from './init'; +import { REVIEW_ID_2 } from './constants'; +import { SendTransactionError } from '@solana/web3.js'; +import { getAccount } from '@solana/spl-token'; + +describe('Gigentic Service Buying SPL Tokens', () => { + it('Checks if the service is paid correctly and escrow has the values supposed', async () => { + const customer = TEST_SERVICE_USERS[1]; + + // Fetch the service registry account + const serviceRegistry = await program.account.serviceRegistry.fetch( + TEST_SERVICE_REGISTRY_KEYPAIR.publicKey, + ); + + // Get the public key of the service account from the registry + const serviceAccountPubKey = serviceRegistry.serviceAccountAddresses[0]; + + // Fetch the service account's data + const serviceAccount = + await program.account.service.fetch(serviceAccountPubKey); + + // Create the transaction to pay for the service + const transaction = new anchor.web3.Transaction().add( + await program.methods + .payServiceSpl(REVIEW_ID_2) + .accounts({ + customer: customer.publicKey, + service: serviceAccountPubKey, + serviceRegistry: TEST_SERVICE_REGISTRY_KEYPAIR.publicKey, + customerTokenAccount: customerTokenAccount, + mint: mint, + }) + .signers([customer]) + .instruction(), + ); + transaction.feePayer = customer.publicKey; + + // Send and confirm the transaction + try { + const txSignature = await anchor.web3.sendAndConfirmTransaction( + connection, + transaction, + [customer], + ); + } catch (err) { + if (err instanceof SendTransactionError) { + // const logs = await err.getLogs(connection); + console.error('Transaction Logs:', err); + } + throw err; + } + + // Verify the escrow account state + const [escrowPubKey] = PublicKey.findProgramAddressSync( + [ + Buffer.from('escrow'), + serviceAccountPubKey.toBuffer(), + serviceAccount.provider.toBuffer(), + customer.publicKey.toBuffer(), + ], + program.programId, + ); + const escrowAccount = await program.account.escrow.fetch(escrowPubKey); + + expect(escrowAccount.expectedAmount.toString()).to.equal( + serviceAccount.price.toString(), + 'Escrow account expected amount should match the service price', + ); + + // Verify the escrow token account balance + const [escrow_token_pkey] = PublicKey.findProgramAddressSync( + [Buffer.from('escrow-token-account'), escrowPubKey.toBuffer()], + program.programId, + ); + + const escrowTokenAccount = await getAccount(connection, escrow_token_pkey); + + expect(escrowTokenAccount.amount.toString()).to.equal( + serviceAccount.price.toString(), + 'Escrow token account balance should match the service price', + ); + const expectedAmount = serviceAccount.price; + expect( + escrowAccount.expectedAmount.toString(), + 'Escrow account expected amount should match the service price', + ).to.equal(expectedAmount.toString()); + const expectedcustomer = customer.publicKey.toBase58(); + expect( + escrowAccount.customer.toBase58(), + 'Escrow account customer should match the customer public key', + ).to.equal(expectedcustomer); + const expectedServiceProvider = + TEST_SERVICE_DEPLOYERS[0].publicKey.toBase58(); + + expect( + escrowAccount.serviceProvider.toBase58(), + "Escrow account service provider should match the service deployer's public key", + ).to.equal(expectedServiceProvider); + const expectedFeeAccount = serviceRegistry.feeAccount.toBase58(); + + expect( + escrowAccount.feeAccount.toBase58(), + "Escrow account fee account should match the service registry's fee account", + ).to.equal(expectedFeeAccount); + + // Check if the escrow account has the correct fee percentage + const expectedFeePercentage = serviceRegistry.feePercentage; + expect( + escrowAccount.feePercentage.toString(), + "Escrow account fee percentage should match the service registry's fee percentage", + ).to.equal(expectedFeePercentage.toString()); + + const service = await program.account.service.fetch(serviceAccountPubKey); + const review = await program.account.review.fetch(service.reviews[1]); + + expect(review.reviewId, 'Review number should match').to.equal(REVIEW_ID_2); + + expect( + review.providerToCustomerRating, + 'Agent to consumer rating should be 0', + ).to.equal(0); + + expect( + review.customerToProviderRating, + 'Consumer to agent rating should be 0', + ).to.equal(0); + + expect( + review.providerToCustomerReview, + 'Agent to customer review should be empty', + ).to.equal(''); + + expect( + review.providerToCustomerReview, + 'Customer to agent review should be empty', + ).to.equal(''); + + expect(service.reviews.length, 'Service should have 1 review').to.equal(2); + }); +}); diff --git a/anchor/tests/provider_to_customer_rating.ts b/anchor/tests/provider_to_customer_rating.ts index 1242ac5..c3d420a 100644 --- a/anchor/tests/provider_to_customer_rating.ts +++ b/anchor/tests/provider_to_customer_rating.ts @@ -5,7 +5,7 @@ import { expect } from 'chai'; import { TEST_SERVICE_DEPLOYERS } from './constants'; describe('Provider to customer review', () => { - it('Rates the customer through the service provider and checks if the values are initialized correctly', async () => { + it('should correctly rate the customer through the service provider for review number 1', async () => { // Select the service provider from the predefined service deployers array // Assume the service provider is the first one in the SERVICE_DEPLOYERS array const serviceProvider = TEST_SERVICE_DEPLOYERS[0]; @@ -38,7 +38,7 @@ describe('Provider to customer review', () => { await program.methods .providerToCustomerRating(rating, review) .accounts({ - signer: serviceProvider.publicKey, + provider: serviceProvider.publicKey, review: serviceAccount.reviews[0], }) .signers([serviceProvider]) @@ -71,6 +71,78 @@ describe('Provider to customer review', () => { 'The rating given by the provider should match the rating stored in the review account.', ); + // Validate that the provider's review comment matches the review stored in the account + expect(reviewAccount.providerToCustomerReview).to.equal( + review, + 'The review comment given by the provider should match the comment stored in the review account.', + ); + }); + it('should correctly rate the customer through the service provider for review number 2', async () => { + // Select the service provider from the predefined service deployers array + // Assume the service provider is the first one in the SERVICE_DEPLOYERS array + const serviceProvider = TEST_SERVICE_DEPLOYERS[0]; + + // Fetch the service registry account from the program, using its public key. + // This registry holds references to various service accounts. + const serviceRegistry = await program.account.serviceRegistry.fetch( + TEST_SERVICE_REGISTRY_KEYPAIR.publicKey, + ); + + // Retrieve the public key of the first service account from the service registry + // Each service account is where reviews, ratings, and interactions are logged. + const serviceAccountPubKey = serviceRegistry.serviceAccountAddresses[0]; + + // Fetch the service account details using the public key + // This account holds data related to the service, such as service provider information. + const serviceAccount = + await program.account.service.fetch(serviceAccountPubKey); + + // The provider's rating for the customer (out of 5) + const rating = 3; + + // The provider's review comment about the customer + const review = 'Nice customer'; + + // Set the fee payer for the transaction. The service provider will pay the fees. + + // Attempt to send and confirm the transaction on the Solana blockchain + try { + await program.methods + .providerToCustomerRating(rating, review) + .accounts({ + provider: serviceProvider.publicKey, + review: serviceAccount.reviews[1], + }) + .signers([serviceProvider]) + .rpc(); + } catch (err) { + // Handle transaction errors + if (err instanceof SendTransactionError) { + console.error('SendTransactionError:', err.message); + } + throw err; // Re-throw the error to make the test fail + } + + // Find the program address for the review account + // This is where the review data (rating, comment) is stored for the specific service + + // Fetch the review account details using the program address + const reviewAccount = await program.account.review.fetch( + serviceAccount.reviews[1], + ); + + // Validate that the service provider for this review matches the expected service provider + expect(reviewAccount.serviceProvider.toBase58()).to.equal( + serviceAccount.provider.toBase58(), + 'The service provider in the review should match the service account provider.', + ); + + // Validate that the provider-to-customer rating in the review matches the rating that was submitted + expect(reviewAccount.providerToCustomerRating).to.equal( + rating, + 'The rating given by the provider should match the rating stored in the review account.', + ); + // Validate that the provider's review comment matches the review stored in the account expect(reviewAccount.providerToCustomerReview).to.equal( review, diff --git a/anchor/tests/sign_service.ts b/anchor/tests/sign_service.ts index b2702f5..6578c7b 100644 --- a/anchor/tests/sign_service.ts +++ b/anchor/tests/sign_service.ts @@ -11,10 +11,10 @@ import { } from './constants'; import { SendTransactionError } from '@solana/web3.js'; -describe('SignService: Transfers money to the service provider and sends fees to the fee account', () => { - it('Transfers money to the service provider and sends fees', async () => { +describe('SignService: Transfer SPL tokens and fees', () => { + it('should transfer SPL tokens to the service provider and send fees to the fee account', async () => { // Select the customer from the predefined service users - const customer = TEST_SERVICE_USERS[0]; + const customer = TEST_SERVICE_USERS[0]; // Select the first service user // Fetch the service registry account const serviceRegistry = await program.account.serviceRegistry.fetch( @@ -39,15 +39,12 @@ describe('SignService: Transfers money to the service provider and sends fees to program.programId, ); - // Fetch the escrow account details - const escrowAccount = await program.account.escrow.fetch(escrowPubKey); - // Construct the transaction to sign the service const transaction = new anchor.web3.Transaction().add( await program.methods .signService() .accounts({ - signer: customer.publicKey, + customer: customer.publicKey, service: serviceAccountPubKey, serviceProvider: TEST_SERVICE_DEPLOYERS[0].publicKey, feeAccount: TEST_FEE_ACCOUNT.publicKey, diff --git a/anchor/tests/sign_service_spl.ts b/anchor/tests/sign_service_spl.ts new file mode 100644 index 0000000..c26da8d --- /dev/null +++ b/anchor/tests/sign_service_spl.ts @@ -0,0 +1,120 @@ +import * as anchor from '@coral-xyz/anchor'; +import { PublicKey } from '@solana/web3.js'; +import { expect } from 'chai'; +import { program, connection } from './init'; +import { + TEST_SERVICE_REGISTRY_KEYPAIR, + TEST_SERVICE_DEPLOYERS, + TEST_SERVICE_USERS, +} from './constants'; +import { feeTokenAccount, serviceProviderTokenAccount } from './init'; + +import { SendTransactionError } from '@solana/web3.js'; +import { getAccount } from '@solana/spl-token'; +import { mint } from './init'; +describe('SignService: Transfers SPL to the service provider and sends fees to the fee account', () => { + it('Transfers money to the service provider and sends fees', async () => { + const customer = TEST_SERVICE_USERS[1]; + + // Fetch the service registry account + const serviceRegistry = await program.account.serviceRegistry.fetch( + TEST_SERVICE_REGISTRY_KEYPAIR.publicKey, + ); + + // Get the public key of the service account from the registry + const serviceAccountPubKey = serviceRegistry.serviceAccountAddresses[0]; + + const serviceAccount = + await program.account.service.fetch(serviceAccountPubKey); + + // Find the program address for the escrow account + const [escrowPubKey, escrowBump] = PublicKey.findProgramAddressSync( + [ + Buffer.from('escrow'), + serviceAccountPubKey.toBuffer(), + serviceAccount.provider.toBuffer(), + customer.publicKey.toBuffer(), + ], + program.programId, + ); + + // Fetch the escrow account details + const escrowAccount = await program.account.escrow.fetch(escrowPubKey); + + const [escrow_token_pkey, escrow_token_bump] = + anchor.web3.PublicKey.findProgramAddressSync( + [Buffer.from('escrow-token-account'), escrowPubKey.toBuffer()], + program.programId, + ); + + const EscrowTokenAccount = await getAccount( + connection, + escrow_token_pkey, + 'confirmed', + ); + + const feeTokenAccountInfo = await getAccount(connection, feeTokenAccount); + + const serviceProviderTokenAccountInfo = await getAccount( + connection, + serviceProviderTokenAccount, + ); + + const serviceProviderTokenAccountBefore = Number( + serviceProviderTokenAccountInfo.amount, + ); + const feeTokenAccountBefore = Number(feeTokenAccountInfo.amount); + + // Construct the transaction to sign the service + const transaction = new anchor.web3.Transaction().add( + await program.methods + .signServiceSpl() + .accounts({ + customer: customer.publicKey, + service: serviceAccountPubKey, + serviceProvider: TEST_SERVICE_DEPLOYERS[0].publicKey, + serviceProviderTokenAccount: serviceProviderTokenAccount, + feeTokenAccount: feeTokenAccount, + mint: mint, + }) + .signers([customer]) + .instruction(), + ); + transaction.feePayer = customer.publicKey; + try { + const txSignature = await anchor.web3.sendAndConfirmTransaction( + connection, + transaction, + [customer], + ); + } catch (err) { + if (err instanceof SendTransactionError) { + } + throw err; + } + + const feeTokenAccountInfoAfter = await getAccount( + connection, + feeTokenAccount, + ); + + const serviceProviderTokenAccountInfoAfter = await getAccount( + connection, + serviceProviderTokenAccount, + ); + + if (escrowAccount.feePercentage == 0) { + expect(Number(feeTokenAccountInfoAfter.amount)).to.equal(0); + expect(Number(serviceProviderTokenAccountInfoAfter.amount)).to.equal( + Number(escrowAccount.expectedAmount), + ); + } else { + expect(Number(feeTokenAccountInfoAfter.amount)).to.be.greaterThan( + Number(0), + ); + expect( + Number(serviceProviderTokenAccountInfoAfter.amount), + ).to.be.greaterThan(Number(serviceProviderTokenAccountBefore)); + } + }); +}); diff --git a/notes/mermaid_diagrams/backup/ERD_blockchain.md b/notes/mermaid_diagrams/backup/ERD_blockchain.md index 99567ff..665126b 100644 --- a/notes/mermaid_diagrams/backup/ERD_blockchain.md +++ b/notes/mermaid_diagrams/backup/ERD_blockchain.md @@ -50,4 +50,3 @@ erDiagram pubkey address PK } ``` - diff --git a/notes/mermaid_diagrams/spl-escrow.md b/notes/mermaid_diagrams/spl-escrow.md new file mode 100644 index 0000000..4332ea8 --- /dev/null +++ b/notes/mermaid_diagrams/spl-escrow.md @@ -0,0 +1,54 @@ +```mermaid +graph TD + SP[Provider]:::providerStyle -.->|Hosts & Pays For| D + M[SPL Token Mint] + D[Provider]:::providerStyle + A[Customer]:::customerStyle + B[Escrow]:::escrowStyle + C[Escrow]:::escrowStyle + E[Fee] + H[Customer]:::customerStyle + + M --> D + M --> E + M --> C + M --> H + + A -->|1 Pay Service| B + + H -->|Transfer| C + + C -->|Stores Address in| B + D -->|Stores Address in| B + B -->|Stores Address for| E + + C -->|2 Sign Service| D + C -->|Transfer Fee| E + + + subgraph "PDA-derived Account" + B + end + + + + subgraph "SPL Accounts" + subgraph "PDA-controlled SPL Accounts" + C + end + D + E + H + end + + classDef customerStyle fill:#ffb366,stroke:#ff9933 + classDef providerStyle fill:#9BB1FA,stroke:#698AF8 + classDef escrowStyle fill:#FAF39B,stroke:#ff9933 + classDef PDAStyle fill:#9BFA9B,stroke:#698AF8 + + A -.->|Hosts & Pays For| H + A -.->|Pays For Creation| B + A -.->|Pays For Creation| C + + +``` diff --git a/package.json b/package.json index 2a46e13..e28d905 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "encoding": "0.1.13", "jotai": "2.8.3", "langchain": "^0.3.2", + "lint": "^0.8.19", "llamaindex": "^0.6.9", "lucide-react": "^0.447.0", "next": "14.2.3", diff --git a/web/app/service-register/page.tsx b/web/app/service-register/page.tsx index 3a029df..8fa0419 100644 --- a/web/app/service-register/page.tsx +++ b/web/app/service-register/page.tsx @@ -1,4 +1,4 @@ -import AddService from '@/components/service-register/add_service'; +import AddService from '@/components/service-register/add-service'; export default function ServicesPage() { return ; diff --git a/web/components/service-register/add_service.tsx b/web/components/service-register/add-service.tsx similarity index 77% rename from web/components/service-register/add_service.tsx rename to web/components/service-register/add-service.tsx index 8e74095..d7ed5eb 100644 --- a/web/components/service-register/add_service.tsx +++ b/web/components/service-register/add-service.tsx @@ -1,42 +1,44 @@ -'use client' +'use client'; -import { useState } from 'react' -import { Button } from '@gigentic-frontend/ui-kit/ui' -import { Card, CardContent, CardFooter } from '@gigentic-frontend/ui-kit/ui' +import { useState } from 'react'; +import { Button } from '@gigentic-frontend/ui-kit/ui'; +import { Card, CardContent, CardFooter } from '@gigentic-frontend/ui-kit/ui'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, -} from '@gigentic-frontend/ui-kit/ui' -import { Textarea } from '@gigentic-frontend/ui-kit/ui' -import { Input } from '@gigentic-frontend/ui-kit/ui' -import { Plus } from 'lucide-react' +} from '@gigentic-frontend/ui-kit/ui'; +import { Textarea } from '@gigentic-frontend/ui-kit/ui'; +import { Input } from '@gigentic-frontend/ui-kit/ui'; +import { Plus } from 'lucide-react'; export default function Component() { - const [serviceDescription, setServiceDescription] = useState('') - const [projectRate, setProjectRate] = useState('') - const [availability, setAvailability] = useState('') + const [serviceDescription, setServiceDescription] = useState(''); + const [projectRate, setProjectRate] = useState(''); + const [availability, setAvailability] = useState(''); const handleCreateService = () => { - console.log('Creating Service Offering...') - console.log('Service Description:', serviceDescription) - console.log('Project Rate:', projectRate) - console.log('Availability:', availability) - console.log('Service offering created successfully.') - } + console.log('Creating Service Offering...'); + console.log('Service Description:', serviceDescription); + console.log('Project Rate:', projectRate); + console.log('Availability:', availability); + console.log('Service offering created successfully.'); + }; return (
-

Create Your Service Offering

+

+ Create Your Service Offering +

Describe your services and set your project rate

- +
- ) -} \ No newline at end of file + ); +} diff --git a/yarn.lock b/yarn.lock index 2c737b4..ed13351 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2374,6 +2374,18 @@ resolved "https://registry.yarnpkg.com/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz#9299f82874bab9e4c7f9c48d865becbfe8d6907c" integrity sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw== +"@kwsites/file-exists@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@kwsites/file-exists/-/file-exists-1.1.1.tgz#ad1efcac13e1987d8dbaf235ef3be5b0d96faa99" + integrity sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw== + dependencies: + debug "^4.1.1" + +"@kwsites/promise-deferred@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz#8ace5259254426ccef57f3175bc64ed7095ed919" + integrity sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw== + "@langchain/core@^0.3.3": version "0.3.3" resolved "https://registry.yarnpkg.com/@langchain/core/-/core-0.3.3.tgz#af12fd767ff2fcedb0a71bd79e6588d7dd52b6b6" @@ -5902,7 +5914,7 @@ ajv-keywords@^5.1.0: dependencies: fast-deep-equal "^3.1.3" -ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -5932,6 +5944,11 @@ ansi-colors@^4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + ansi-escapes@^4.2.1: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -5944,6 +5961,16 @@ ansi-html-community@^0.0.8: resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== +ansi-regex@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== + +ansi-regex@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -5954,7 +5981,7 @@ ansi-regex@^6.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== -ansi-styles@^3.2.1: +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -6154,6 +6181,13 @@ arraybuffer.prototype.slice@^1.0.3: is-array-buffer "^3.0.4" is-shared-array-buffer "^1.0.2" +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + assemblyai@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/assemblyai/-/assemblyai-4.7.0.tgz#852670f9a24d540b1b56d298eed26bc4f75df4c4" @@ -6161,6 +6195,11 @@ assemblyai@^4.7.0: dependencies: ws "^8.17.1" +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + ast-types-flow@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" @@ -6226,6 +6265,16 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.13.2" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" + integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== + axe-core@^4.10.0, axe-core@^4.6.2: version "4.10.0" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.0.tgz#d9e56ab0147278272739a000880196cdfe113b59" @@ -6409,6 +6458,13 @@ batch@0.6.1: resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -6715,7 +6771,7 @@ camelcase@^4.1.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" integrity sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw== -camelcase@^5.3.1: +camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== @@ -6744,7 +6800,12 @@ canvas@^2.11.2: nan "^2.17.0" simple-get "^3.0.3" -chalk@^2.4.2: +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + +chalk@^2.0.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -6771,6 +6832,11 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + chokidar@^3.5.3: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" @@ -6835,6 +6901,13 @@ cli-cursor@3.1.0, cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== + dependencies: + restore-cursor "^2.0.0" + cli-cursor@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" @@ -6847,16 +6920,37 @@ cli-spinners@2.6.1: resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== -cli-spinners@^2.5.0, cli-spinners@^2.6.1: +cli-spinners@^2.0.0, cli-spinners@^2.5.0, cli-spinners@^2.6.1: version "2.9.2" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== +cli-table@^0.3.1: + version "0.3.11" + resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.11.tgz#ac69cdecbe81dccdba4889b9a18b7da312a9d3ee" + integrity sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ== + dependencies: + colors "1.0.3" + +cli-width@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" + integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== + client-only@0.0.1, client-only@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -7002,6 +7096,11 @@ colorette@^2.0.10, colorette@^2.0.20: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== +colors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + integrity sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw== + colorspace@1.1.x: version "1.1.4" resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" @@ -7018,7 +7117,7 @@ columnify@^1.6.0: strip-ansi "^6.0.1" wcwidth "^1.0.0" -combined-stream@^1.0.8: +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -7035,7 +7134,7 @@ commander@^12.0.0, commander@^12.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== -commander@^2.20.0, commander@^2.20.3: +commander@^2.17.1, commander@^2.20.0, commander@^2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -7165,6 +7264,11 @@ core-js-compat@^3.37.1, core-js-compat@^3.38.0: dependencies: browserslist "^4.23.3" +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -7509,6 +7613,13 @@ damerau-levenshtein@^1.0.8: resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + data-uri-to-buffer@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" @@ -7576,7 +7687,7 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -decamelize@1.2.0: +decamelize@1.2.0, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== @@ -7911,6 +8022,14 @@ eastasianwidth@^0.2.0: resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" @@ -7940,6 +8059,11 @@ emittery@^0.13.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -8672,11 +8796,37 @@ ext-name@^5.0.0: ext-list "^2.0.0" sort-keys-length "^1.0.0" -extend@^3.0.2: +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +extend@^3.0.2, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + eyes@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" @@ -8795,6 +8945,13 @@ figures@3.2.0: dependencies: escape-string-regexp "^1.0.5" +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -8882,6 +9039,13 @@ find-cache-dir@^4.0.0: common-path-prefix "^3.0.0" pkg-dir "^7.0.0" +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -8957,6 +9121,11 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + fork-ts-checker-webpack-plugin@7.2.13: version "7.2.13" resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-7.2.13.tgz#51ffd6a2f96f03ab64b92f8aedf305dbf3dee0f1" @@ -8994,6 +9163,15 @@ form-data@4.0.0, form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + formdata-node@^4.3.2: version "4.4.1" resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.4.1.tgz#23f6a5cb9cb55315912cbec4ff7b0f59bbd191e2" @@ -9041,6 +9219,11 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== +fs-exists-sync@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" + integrity sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg== + fs-extra@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" @@ -9179,7 +9362,7 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-caller-file@^2.0.5: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -9243,6 +9426,13 @@ get-tsconfig@^4.7.5: dependencies: resolve-pkg-maps "^1.0.0" +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -9456,6 +9646,19 @@ handle-thing@^2.0.0: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + harmony-reflect@^1.4.6: version "1.6.2" resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.2.tgz#31ecbd32e648a34d030d86adb67d4d47547fe710" @@ -9648,6 +9851,15 @@ http-server@^14.1.0: union "~0.5.0" url-join "^4.0.1" +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + http2-wrapper@^1.0.0-beta.5.2: version "1.0.3" resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" @@ -9697,7 +9909,7 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-lite@0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -9818,6 +10030,25 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== +inquirer@^6.1.0: + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + internal-slot@^1.0.4, internal-slot@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" @@ -9944,6 +10175,11 @@ is-docker@^2.0.0, is-docker@^2.1.1: resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== +is-extendable@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -9956,6 +10192,11 @@ is-finalizationregistry@^1.0.2: dependencies: call-bind "^1.0.2" +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -10127,6 +10368,11 @@ is-typed-array@^1.1.13: dependencies: which-typed-array "^1.1.14" +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + is-unicode-supported@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" @@ -10202,6 +10448,11 @@ isomorphic-ws@^4.0.1: resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== + istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" @@ -10725,7 +10976,14 @@ js-tiktoken@^1.0.12, js-tiktoken@^1.0.14: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.10.0, js-yaml@^3.13.1: +js-yaml@>=3.13.1, js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +js-yaml@^3.10.0, js-yaml@^3.13.1, js-yaml@^3.8.3: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -10733,12 +10991,10 @@ js-yaml@^3.10.0, js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== jsdom@^20.0.0: version "20.0.3" @@ -10819,7 +11075,7 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json-stringify-safe@^5.0.1: +json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== @@ -10914,6 +11170,16 @@ jsonwebtoken@^9.0.0: ms "^2.1.1" semver "^7.5.4" +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.3, jsx-ast-utils@^3.3.5: version "3.3.5" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" @@ -11128,6 +11394,25 @@ lines-and-columns@~2.0.3: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-2.0.4.tgz#d00318855905d2660d8c0822e3f5a4715855fc42" integrity sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A== +lint@^0.8.19: + version "0.8.19" + resolved "https://registry.yarnpkg.com/lint/-/lint-0.8.19.tgz#5be18853dbc96053b74bdfa2bb5c9c4c30e59216" + integrity sha512-i9iqBX/OO2+zSE7hEDXJ0rdLMxvBluK2T/xbCKAhEgyHE1q6kjp1HJGOVagkVB0f0UZ+FnW/wM3smsihQN0tFw== + dependencies: + chalk "^2.4.2" + cli-table "^0.3.1" + commander "^2.17.1" + inquirer "^6.1.0" + js-yaml ">=3.13.1" + loadash "^1.0.0" + moment "^2.22.2" + ora "^3.0.0" + prettier "^1.15.3" + replace-in-file "^3.4.2" + request "^2.87.0" + simple-git "^3.15.0" + write-yaml "^1.0.0" + llamaindex@^0.6.9: version "0.6.9" resolved "https://registry.yarnpkg.com/llamaindex/-/llamaindex-0.6.9.tgz#13b95f647b320378ec2cf7c6c7d2de443eacaf21" @@ -11184,6 +11469,11 @@ llamaindex@^0.6.9: wink-nlp "^2.3.0" zod "^3.23.8" +loadash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/loadash/-/loadash-1.0.0.tgz#b92e54d809f3c225f4f9a9cfbaeae5b56de1ca9f" + integrity sha512-xlX5HBsXB3KG0FJbJJG/3kYWCfsCyCSus3T+uHVu6QL6YxAdggmm3QeyLgn54N2yi5/UE6xxL5ZWJAAiHzHYEg== + loader-runner@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" @@ -11203,6 +11493,14 @@ loader-utils@^3.2.0: resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.3.1.tgz#735b9a19fd63648ca7adbd31c2327dfe281304e5" integrity sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg== +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -11314,11 +11612,18 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -lodash@^4.17.14, lodash@^4.17.21, lodash@^4.17.4: +lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +log-symbols@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + log-symbols@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" @@ -11554,7 +11859,7 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -11566,6 +11871,11 @@ mime@1.6.0, mime@^1.4.1, mime@^1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -11673,7 +11983,7 @@ minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" -mkdirp@^0.5.6: +mkdirp@^0.5.1, mkdirp@^0.5.6: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -11695,6 +12005,11 @@ mkdirp@^3.0.1: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== +moment@^2.22.2: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + mongodb-connection-string-url@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz#c13e6ac284ae401752ebafdb8cd7f16c6723b141" @@ -11735,6 +12050,11 @@ mustache@^4.2.0: resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== + mz@^2.6.0, mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -12026,6 +12346,11 @@ nx@19.3.2: "@nx/nx-win32-arm64-msvc" "19.3.2" "@nx/nx-win32-x64-msvc" "19.3.2" +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + object-assign@^4.0.1, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -12141,6 +12466,13 @@ one-time@^1.0.0: dependencies: fn.name "1.x.x" +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== + dependencies: + mimic-fn "^1.0.0" + onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -12231,6 +12563,18 @@ ora@5.3.0: strip-ansi "^6.0.0" wcwidth "^1.0.1" +ora@^3.0.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" + integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg== + dependencies: + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-spinners "^2.0.0" + log-symbols "^2.2.0" + strip-ansi "^5.2.0" + wcwidth "^1.0.1" + ora@^6.1.2: version "6.3.1" resolved "https://registry.yarnpkg.com/ora/-/ora-6.3.1.tgz#a4e9e5c2cf5ee73c259e8b410273e706a2ad3ed6" @@ -12253,6 +12597,11 @@ os-filter-obj@^2.0.0: dependencies: arch "^2.1.0" +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + p-cancelable@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" @@ -12263,7 +12612,7 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== -p-limit@^2.2.0: +p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== @@ -12284,6 +12633,13 @@ p-limit@^4.0.0: dependencies: yocto-queue "^1.0.0" +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + p-locate@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" @@ -12397,6 +12753,11 @@ path-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -12460,6 +12821,11 @@ peek-readable@^5.1.3: resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-5.2.0.tgz#7458f18126217c154938c32a185f5d05f3df3710" integrity sha512-U94a+eXHzct7vAd19GH3UQ2dH4Satbng0MyYTMaQatL0pvYYL5CTPR25HBhKtecl+4bfu1/i3vC6k0hydO5Vcw== +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + pg-int8@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" @@ -13132,6 +13498,11 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prettier@^1.15.3: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== + prettier@^2.6.2: version "2.8.8" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" @@ -13229,6 +13600,13 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== +psl@^1.1.28: + version "1.13.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.13.0.tgz#8b2357f13ef3cf546af3f52de00543a94da86cfa" + integrity sha512-BFwmFXiJoFqlUpZ5Qssolv15DMyc84gTBds1BjsV1BfXEo1UyyD7GsmN67n7J77uRhoSNW1AXtXKPLcBFQn9Aw== + dependencies: + punycode "^2.3.1" + psl@^1.1.33: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -13242,7 +13620,7 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0: +punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0, punycode@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== @@ -13266,6 +13644,11 @@ qs@6.13.0, qs@^6.4.0: dependencies: side-channel "^1.0.6" +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + querystringify@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" @@ -13569,6 +13952,41 @@ remeda@^2.12.0: dependencies: type-fest "^4.26.1" +replace-in-file@^3.4.2: + version "3.4.4" + resolved "https://registry.yarnpkg.com/replace-in-file/-/replace-in-file-3.4.4.tgz#2c2b95a493dc4f6161c2bcd29a661be16d03d323" + integrity sha512-ehq0dFsxSpfPiPLBU5kli38Ud8bZL0CQKG8WQVbvhmyilXaMJ8y4LtDZs/K3MD8C0+rHbsfW8c9r2bUEy0B/6Q== + dependencies: + chalk "^2.4.2" + glob "^7.1.3" + yargs "^13.2.2" + +request@^2.87.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -13579,6 +13997,11 @@ require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" @@ -13646,6 +14069,14 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -13785,6 +14216,11 @@ rpc-websockets@^9.0.2: bufferutil "^4.0.1" utf-8-validate "^5.0.2" +run-async@^2.2.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -13792,6 +14228,13 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rxjs@^6.4.0: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + rxjs@^7.5.2, rxjs@^7.8.0: version "7.8.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" @@ -13814,7 +14257,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -13838,7 +14281,7 @@ safe-stable-stringify@^2.3.1, safe-stable-stringify@^2.4.3: resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -14148,6 +14591,15 @@ simple-get@^3.0.3: once "^1.3.1" simple-concat "^1.0.0" +simple-git@^3.15.0: + version "3.27.0" + resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-3.27.0.tgz#f4b09e807bda56a4a3968f635c0e4888d3decbd5" + integrity sha512-ivHoFS9Yi9GY49ogc6/YAi3Fl9ROnF4VyubNylgCkA+RVqLaKWnDSzXOVzya8csELIaWaYNutsEuAhZrtOjozA== + dependencies: + "@kwsites/file-exists" "^1.1.1" + "@kwsites/promise-deferred" "^1.1.1" + debug "^4.3.5" + simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" @@ -14283,6 +14735,21 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== +sshpk@^1.7.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" + integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + sswr@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/sswr/-/sswr-2.1.0.tgz#1eb64cd647cc9e11f871e7f43554abd8c64e1103" @@ -14403,6 +14870,23 @@ string-trim-spaces-only@^5.0.10: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -14504,6 +14988,20 @@ stringify-object@^5.0.0: dependencies: ansi-regex "^5.0.1" +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -14874,7 +15372,7 @@ through2@^4.0.2: dependencies: readable-stream "3" -"through@>=2.2.7 <3", through@^2.3.4: +"through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -14894,6 +15392,13 @@ tiny-invariant@^1.3.3: resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + tmp@~0.2.1: version "0.2.3" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" @@ -14949,6 +15454,14 @@ tough-cookie@^4.0.0, tough-cookie@^4.1.2: universalify "^0.2.0" url-parse "^1.5.3" +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + tr46@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" @@ -15103,7 +15616,7 @@ tsconfig-paths@^4.0.0, tsconfig-paths@^4.1.2, tsconfig-paths@^4.2.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.11.1: +tslib@^1.11.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -15113,6 +15626,18 @@ tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3 resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -15390,6 +15915,11 @@ uuid@^10.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294" integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ== +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + uuid@^8.3.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" @@ -15429,6 +15959,15 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + w3c-xmlserializer@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073" @@ -15693,6 +16232,11 @@ which-collection@^1.0.1, which-collection@^1.0.2: is-weakmap "^2.0.2" is-weakset "^2.0.3" +which-module@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + which-typed-array@^1.1.13, which-typed-array@^1.1.14, which-typed-array@^1.1.15: version "1.1.15" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" @@ -15783,6 +16327,15 @@ word-wrap@^1.2.5: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -15814,6 +16367,23 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" +write-yaml@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/write-yaml/-/write-yaml-1.0.0.tgz#314596119d0db91247cbc835bce0033b6e0ba09e" + integrity sha512-QFB0QwNlUTSsICNb1HV+822MvFpTC1gtKcOfm0B9oqz4qOQXbRuMSxWPWryTEFBEZDWbI5zXabXArvShXTdLiA== + dependencies: + extend-shallow "^2.0.1" + js-yaml "^3.8.3" + write "^0.3.3" + +write@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/write/-/write-0.3.3.tgz#09cdc5a2155607ee279f45e38d91ae29fb6a5178" + integrity sha512-e63bsTAFxFUU8OGClhjhhf2R72Njpq6DDTOFFBxDkfZFwoRRKZUx9rll6g/TvY0UcCdKE2OroYZje0v9ROzmfA== + dependencies: + fs-exists-sync "^0.1.0" + mkdirp "^0.5.1" + ws@^7.5.10: version "7.5.10" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" @@ -15839,6 +16409,11 @@ xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -15874,6 +16449,30 @@ yargs-parser@21.1.1, yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== +yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@^13.2.2: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" + yargs@^17.3.1, yargs@^17.6.2, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"