From 3c68467a4314b33a987a05f4f5af1419212c9cce Mon Sep 17 00:00:00 2001 From: David Leng Date: Mon, 2 Sep 2024 13:23:52 +0800 Subject: [PATCH] feat: version 0.1.0 --- Anchor.toml | 3 + app/src/idl/blinkmart_protocol.ts | 870 ++++++++++++++++++ package.json | 16 +- programs/blinkmart-protocol/src/error.rs | 4 +- .../src/instructions/cancel_order.rs | 29 +- .../src/instructions/confirm_receipt.rs | 4 +- .../src/instructions/delisting.rs | 21 +- .../src/instructions/initialize.rs | 42 +- .../src/instructions/listing.rs | 8 +- .../src/instructions/place_order.rs | 2 +- .../src/instructions/seller_withdraw.rs | 44 +- programs/blinkmart-protocol/src/lib.rs | 6 +- .../blinkmart-protocol/src/state/order.rs | 2 +- .../blinkmart-protocol/src/state/product.rs | 2 +- tests/blinkmart-protocol.ts | 229 ++++- yarn.lock | 189 +++- 16 files changed, 1391 insertions(+), 80 deletions(-) create mode 100644 app/src/idl/blinkmart_protocol.ts diff --git a/Anchor.toml b/Anchor.toml index 00f8358..747c359 100644 --- a/Anchor.toml +++ b/Anchor.toml @@ -16,3 +16,6 @@ wallet = "~/.config/solana/id.json" [scripts] test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" + +[workspace] +types = "app/src/idl/" diff --git a/app/src/idl/blinkmart_protocol.ts b/app/src/idl/blinkmart_protocol.ts new file mode 100644 index 0000000..81d5d6e --- /dev/null +++ b/app/src/idl/blinkmart_protocol.ts @@ -0,0 +1,870 @@ +/** + * Program IDL in camelCase format in order to be used in JS/TS. + * + * Note that this is only a type helper and is not the actual IDL. The original + * IDL can be found at `target/idl/blinkmart_protocol.json`. + */ +export type BlinkmartProtocol = { + "address": "GSa7icw4GkCW5Lnqdz53BVhX3V9tx8MPY7XZxR8BAixS", + "metadata": { + "name": "blinkmartProtocol", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [ + { + "name": "cancelOrder", + "discriminator": [ + 95, + 129, + 237, + 240, + 8, + 49, + 223, + 132 + ], + "accounts": [ + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "product", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 114, + 111, + 100, + 117, + 99, + 116 + ] + }, + { + "kind": "arg", + "path": "params.product_id" + } + ] + } + }, + { + "name": "order", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 111, + 114, + 100, + 101, + 114 + ] + }, + { + "kind": "arg", + "path": "params.order_id" + } + ] + } + }, + { + "name": "admin", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110 + ] + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": { + "name": "cancelOrderParams" + } + } + } + ] + }, + { + "name": "confirmReceipt", + "discriminator": [ + 203, + 36, + 80, + 115, + 249, + 12, + 141, + 170 + ], + "accounts": [ + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "product", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 114, + 111, + 100, + 117, + 99, + 116 + ] + }, + { + "kind": "arg", + "path": "params.product_id" + } + ] + } + }, + { + "name": "order", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 111, + 114, + 100, + 101, + 114 + ] + }, + { + "kind": "arg", + "path": "params.order_id" + } + ] + } + }, + { + "name": "admin", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110 + ] + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": { + "name": "confirmReceiptParams" + } + } + } + ] + }, + { + "name": "delisting", + "discriminator": [ + 35, + 182, + 48, + 175, + 111, + 180, + 118, + 31 + ], + "accounts": [ + { + "name": "administrator", + "writable": true, + "signer": true + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "product", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 114, + 111, + 100, + 117, + 99, + 116 + ] + }, + { + "kind": "arg", + "path": "params.product_id" + } + ] + } + }, + { + "name": "admin", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110 + ] + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": { + "name": "delistingParams" + } + } + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "admin", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110 + ] + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": { + "name": "initializeParams" + } + } + } + ] + }, + { + "name": "listing", + "discriminator": [ + 126, + 47, + 161, + 107, + 23, + 112, + 254, + 126 + ], + "accounts": [ + { + "name": "authority", + "writable": true, + "signer": true + }, + { + "name": "product", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 114, + 111, + 100, + 117, + 99, + 116 + ] + }, + { + "kind": "arg", + "path": "params.product_id" + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": { + "name": "listingParams" + } + } + } + ] + }, + { + "name": "placeOrder", + "discriminator": [ + 51, + 194, + 155, + 175, + 109, + 130, + 96, + 106 + ], + "accounts": [ + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "product", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 114, + 111, + 100, + 117, + 99, + 116 + ] + }, + { + "kind": "arg", + "path": "params.product_id" + } + ] + } + }, + { + "name": "order", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 111, + 114, + 100, + 101, + 114 + ] + }, + { + "kind": "arg", + "path": "params.order_id" + } + ] + } + }, + { + "name": "admin", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110 + ] + } + ] + } + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": { + "name": "placeOrderParams" + } + } + } + ] + }, + { + "name": "sellerWithdraw", + "discriminator": [ + 151, + 183, + 229, + 20, + 161, + 5, + 96, + 15 + ], + "accounts": [ + { + "name": "treasury", + "writable": true + }, + { + "name": "product", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 114, + 111, + 100, + 117, + 99, + 116 + ] + }, + { + "kind": "arg", + "path": "params.product_id" + } + ] + } + }, + { + "name": "admin", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 97, + 100, + 109, + 105, + 110 + ] + } + ] + } + }, + { + "name": "administrator", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "params", + "type": { + "defined": { + "name": "sellerWithdrawParams" + } + } + } + ] + } + ], + "accounts": [ + { + "name": "admin", + "discriminator": [ + 244, + 158, + 220, + 65, + 8, + 73, + 4, + 65 + ] + }, + { + "name": "order", + "discriminator": [ + 134, + 173, + 223, + 185, + 77, + 86, + 28, + 51 + ] + }, + { + "name": "product", + "discriminator": [ + 102, + 76, + 55, + 251, + 38, + 73, + 224, + 229 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "invalidOrder", + "msg": "Invalid order id" + }, + { + "code": 6001, + "name": "invalidProduct", + "msg": "Invalid product id" + }, + { + "code": 6002, + "name": "invalidTreasury", + "msg": "Invalid treasury address" + } + ], + "types": [ + { + "name": "admin", + "type": { + "kind": "struct", + "fields": [ + { + "name": "administrator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "operation", + "type": "pubkey" + }, + { + "name": "transactionFees", + "type": "u16" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "cancelOrderParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "orderId", + "type": "string" + }, + { + "name": "productId", + "type": "string" + } + ] + } + }, + { + "name": "confirmReceiptParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "orderId", + "type": "string" + }, + { + "name": "productId", + "type": "string" + } + ] + } + }, + { + "name": "delistingParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "productId", + "type": "string" + } + ] + } + }, + { + "name": "initializeParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "administrator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "operation", + "type": "pubkey" + }, + { + "name": "transactionFees", + "type": "u16" + } + ] + } + }, + { + "name": "listingParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "productId", + "type": "string" + }, + { + "name": "administrator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "salesPrice", + "type": "u64" + } + ] + } + }, + { + "name": "order", + "type": { + "kind": "struct", + "fields": [ + { + "name": "orderId", + "type": "string" + }, + { + "name": "payer", + "type": "pubkey" + }, + { + "name": "amount", + "type": "u64" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "placeOrderParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "orderId", + "type": "string" + }, + { + "name": "productId", + "type": "string" + }, + { + "name": "payer", + "type": "pubkey" + }, + { + "name": "orderQuantity", + "type": "u64" + } + ] + } + }, + { + "name": "product", + "type": { + "kind": "struct", + "fields": [ + { + "name": "productId", + "type": "string" + }, + { + "name": "administrator", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + }, + { + "name": "salesPrice", + "type": "u64" + }, + { + "name": "salesAmount", + "type": "u64" + }, + { + "name": "bump", + "type": "u8" + } + ] + } + }, + { + "name": "sellerWithdrawParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "productId", + "type": "string" + } + ] + } + } + ], + "constants": [ + { + "name": "admin", + "type": "string", + "value": "\"admin\"" + }, + { + "name": "order", + "type": "string", + "value": "\"order\"" + }, + { + "name": "product", + "type": "string", + "value": "\"product\"" + } + ] +}; diff --git a/package.json b/package.json index 04daffe..61bfd3a 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,22 @@ { - "license": "ISC", + "license": "ISC", "scripts": { "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" }, "dependencies": { - "@coral-xyz/anchor": "^0.30.1" + "@coral-xyz/anchor": "^0.30.1", + "@solana/spl-token": "^0.4.8", + "@solana/web3.js": "^1.95.3" }, "devDependencies": { - "chai": "^4.3.4", - "mocha": "^9.0.3", - "ts-mocha": "^10.0.0", "@types/bn.js": "^5.1.0", "@types/chai": "^4.3.0", "@types/mocha": "^9.0.0", - "typescript": "^4.3.5", - "prettier": "^2.6.2" + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^4.3.5" } } diff --git a/programs/blinkmart-protocol/src/error.rs b/programs/blinkmart-protocol/src/error.rs index 26b5a94..279c3ab 100644 --- a/programs/blinkmart-protocol/src/error.rs +++ b/programs/blinkmart-protocol/src/error.rs @@ -3,9 +3,9 @@ use anchor_lang::prelude::*; #[error_code] pub enum ErrorCode { #[msg("Invalid order id")] - InvalidOrderId, + InvalidOrder, #[msg("Invalid product id")] - InvalidProductId, + InvalidProduct, #[msg("Invalid treasury address")] InvalidTreasury, } diff --git a/programs/blinkmart-protocol/src/instructions/cancel_order.rs b/programs/blinkmart-protocol/src/instructions/cancel_order.rs index b737267..e363c81 100644 --- a/programs/blinkmart-protocol/src/instructions/cancel_order.rs +++ b/programs/blinkmart-protocol/src/instructions/cancel_order.rs @@ -1,25 +1,23 @@ use anchor_lang::prelude::*; -use anchor_lang::system_program; - use crate::error::ErrorCode; use crate::{Admin, Order, Product, ADMIN, ORDER, PRODUCT}; pub fn cancel_order(ctx: Context, _params: CancelOrderParams) -> Result<()> { - require!(ctx.accounts.order.bump.ne(&0), ErrorCode::InvalidOrderId); + require!(ctx.accounts.order.bump.ne(&0), ErrorCode::InvalidOrder); - let amount = ctx.accounts.order.amount; + let order_amount = ctx.accounts.order.amount; - system_program::transfer( - CpiContext::new( - ctx.accounts.system_program.to_account_info(), - system_program::Transfer { - from: ctx.accounts.admin.to_account_info(), - to: ctx.accounts.payer.to_account_info(), - }, - ), - amount, - )?; + **ctx + .accounts + .admin + .to_account_info() + .try_borrow_mut_lamports()? -= order_amount; + **ctx + .accounts + .payer + .to_account_info() + .try_borrow_mut_lamports()? += order_amount; Ok(()) } @@ -33,7 +31,7 @@ pub struct CancelOrderParams { #[derive(Accounts)] #[instruction(params: CancelOrderParams)] pub struct CancelOrder<'info> { - #[account(mut)] + #[account(mut, address = order.payer)] pub payer: Signer<'info>, #[account( @@ -52,6 +50,7 @@ pub struct CancelOrder<'info> { ORDER.as_bytes(), params.order_id.as_bytes() ], + close=payer, bump )] pub order: Box>, diff --git a/programs/blinkmart-protocol/src/instructions/confirm_receipt.rs b/programs/blinkmart-protocol/src/instructions/confirm_receipt.rs index f9de5f9..769edcd 100644 --- a/programs/blinkmart-protocol/src/instructions/confirm_receipt.rs +++ b/programs/blinkmart-protocol/src/instructions/confirm_receipt.rs @@ -4,7 +4,9 @@ use crate::{Admin, Order, Product, ADMIN, ORDER, PRODUCT}; use anchor_lang::prelude::*; pub fn confirm_receipt(ctx: Context, _params: ConfirmReceiptParams) -> Result<()> { - require!(ctx.accounts.order.bump.ne(&0), ErrorCode::InvalidOrderId); + require!(ctx.accounts.order.bump.ne(&0), ErrorCode::InvalidOrder); + + ctx.accounts.product.sales_amount += ctx.accounts.order.amount; Ok(()) } diff --git a/programs/blinkmart-protocol/src/instructions/delisting.rs b/programs/blinkmart-protocol/src/instructions/delisting.rs index 51fba75..85a8bdd 100644 --- a/programs/blinkmart-protocol/src/instructions/delisting.rs +++ b/programs/blinkmart-protocol/src/instructions/delisting.rs @@ -2,7 +2,6 @@ use crate::error::ErrorCode; use anchor_lang::prelude::*; use crate::{Admin, Product, ADMIN, PRODUCT}; -use anchor_lang::system_program; pub fn delisting(ctx: Context, _params: DelistingParams) -> Result<()> { let mut withdraw_amount = ctx.accounts.product.sales_amount; @@ -15,16 +14,16 @@ pub fn delisting(ctx: Context, _params: DelistingParams) -> Result<() .checked_div(10000) .unwrap(); - system_program::transfer( - CpiContext::new( - ctx.accounts.system_program.to_account_info(), - system_program::Transfer { - from: ctx.accounts.admin.to_account_info(), - to: ctx.accounts.treasury.to_account_info(), - }, - ), - withdraw_amount, - )?; + **ctx + .accounts + .admin + .to_account_info() + .try_borrow_mut_lamports()? -= withdraw_amount; + **ctx + .accounts + .treasury + .to_account_info() + .try_borrow_mut_lamports()? += withdraw_amount; } Ok(()) } diff --git a/programs/blinkmart-protocol/src/instructions/initialize.rs b/programs/blinkmart-protocol/src/instructions/initialize.rs index 5145869..54c82c8 100644 --- a/programs/blinkmart-protocol/src/instructions/initialize.rs +++ b/programs/blinkmart-protocol/src/instructions/initialize.rs @@ -1,9 +1,43 @@ use anchor_lang::prelude::*; -#[derive(Accounts)] -pub struct Initialize {} +use crate::{Admin, ADMIN}; + +pub fn initialize(ctx: Context, params: InitializeParams) -> Result<()> { + ctx.accounts.admin.set_inner(Admin { + administrator: params.administrator, + treasury: params.treasury, + operation: params.operation, + transaction_fees: params.transaction_fees, + bump: ctx.bumps.admin, + }); -pub fn initialize(ctx: Context) -> Result<()> { - msg!("Greetings from: {:?}", ctx.program_id); Ok(()) } + +#[derive(Clone, AnchorSerialize, AnchorDeserialize)] +pub struct InitializeParams { + administrator: Pubkey, + treasury: Pubkey, + operation: Pubkey, + transaction_fees: u16, +} + +#[derive(Accounts)] +#[instruction(params: InitializeParams)] +pub struct Initialize<'info> { + #[account(mut)] + pub payer: Signer<'info>, + + #[account( + init, + space=Admin::LEN, + payer = payer, + seeds=[ + ADMIN.as_bytes(), + ], + bump + )] + pub admin: Box>, + + pub system_program: Program<'info, System>, +} diff --git a/programs/blinkmart-protocol/src/instructions/listing.rs b/programs/blinkmart-protocol/src/instructions/listing.rs index 929f38e..8ac6375 100644 --- a/programs/blinkmart-protocol/src/instructions/listing.rs +++ b/programs/blinkmart-protocol/src/instructions/listing.rs @@ -6,6 +6,7 @@ pub fn listing(ctx: Context, params: ListingParams) -> Result<()> { ctx.accounts.product.set_inner(Product { product_id: params.product_id, administrator: params.administrator, + // administrator: ctx.accounts.authority.key(), treasury: params.treasury, sales_price: params.sales_price, // inventory: params.inventory, @@ -21,22 +22,23 @@ pub struct ListingParams { administrator: Pubkey, treasury: Pubkey, sales_price: u64, - inventory: u64, + // inventory: u64, } #[derive(Accounts)] #[instruction(params: ListingParams)] pub struct Listing<'info> { #[account(mut)] - pub administrator: Signer<'info>, + pub authority: Signer<'info>, #[account( init, space= Product::LEN, - payer = administrator, + payer = authority, seeds=[ PRODUCT.as_bytes(), params.product_id.as_bytes(), + // &hash::hash(params.product_id.as_bytes()).to_bytes() ], bump )] diff --git a/programs/blinkmart-protocol/src/instructions/place_order.rs b/programs/blinkmart-protocol/src/instructions/place_order.rs index 7cdc75f..c2c00a9 100644 --- a/programs/blinkmart-protocol/src/instructions/place_order.rs +++ b/programs/blinkmart-protocol/src/instructions/place_order.rs @@ -5,7 +5,7 @@ use anchor_lang::system_program; use crate::error::ErrorCode; use crate::{Admin, Order, Product, ADMIN, ORDER, PRODUCT}; pub fn place_order(ctx: Context, params: PlaceOrderParams) -> Result<()> { - require!(ctx.accounts.order.bump.eq(&0), ErrorCode::InvalidOrderId); + require!(ctx.accounts.order.bump.eq(&0), ErrorCode::InvalidOrder); let amount = params .order_quantity diff --git a/programs/blinkmart-protocol/src/instructions/seller_withdraw.rs b/programs/blinkmart-protocol/src/instructions/seller_withdraw.rs index b548f36..d8816e6 100644 --- a/programs/blinkmart-protocol/src/instructions/seller_withdraw.rs +++ b/programs/blinkmart-protocol/src/instructions/seller_withdraw.rs @@ -1,36 +1,38 @@ use anchor_lang::prelude::*; use crate::error::ErrorCode; -use anchor_lang::system_program; use crate::{Admin, Product, ADMIN, PRODUCT}; pub fn seller_withdraw(ctx: Context, _params: SellerWithdrawParams) -> Result<()> { - require!( - ctx.accounts.product.bump.ne(&0), - ErrorCode::InvalidProductId - ); + require!(ctx.accounts.product.bump.ne(&0), ErrorCode::InvalidProduct); - let transaction_fee = ctx.accounts.admin.transaction_fees; // 500 -> 5% - let withdraw_amount = ctx + // let transaction_fee = ctx.accounts.admin.transaction_fees; // 500 -> 5% + let transaction_fee = ctx .accounts .product .sales_amount - .checked_mul(transaction_fee as u64) + .checked_mul(ctx.accounts.admin.transaction_fees as u64) .unwrap() .checked_div(10000) .unwrap(); + let withdraw_amount = ctx + .accounts + .product + .sales_amount + .checked_sub(transaction_fee) + .unwrap(); - system_program::transfer( - CpiContext::new( - ctx.accounts.system_program.to_account_info(), - system_program::Transfer { - from: ctx.accounts.admin.to_account_info(), - to: ctx.accounts.treasury.to_account_info(), - }, - ), - withdraw_amount, - )?; + **ctx + .accounts + .admin + .to_account_info() + .try_borrow_mut_lamports()? -= withdraw_amount; + **ctx + .accounts + .treasury + .to_account_info() + .try_borrow_mut_lamports()? += withdraw_amount; Ok(()) } @@ -43,9 +45,6 @@ pub struct SellerWithdrawParams { #[derive(Accounts)] #[instruction(params: SellerWithdrawParams)] pub struct SellerWithdraw<'info> { - #[account(mut, address = product.administrator)] - pub administrator: Signer<'info>, - /// CHECK: #[account(mut, address = product.treasury @ ErrorCode::InvalidTreasury)] pub treasury: UncheckedAccount<'info>, @@ -69,5 +68,8 @@ pub struct SellerWithdraw<'info> { )] pub admin: Box>, + #[account(mut, address = product.administrator)] + pub administrator: Signer<'info>, + pub system_program: Program<'info, System>, } diff --git a/programs/blinkmart-protocol/src/lib.rs b/programs/blinkmart-protocol/src/lib.rs index 9403391..064bb55 100644 --- a/programs/blinkmart-protocol/src/lib.rs +++ b/programs/blinkmart-protocol/src/lib.rs @@ -12,11 +12,11 @@ pub use state::*; declare_id!("GSa7icw4GkCW5Lnqdz53BVhX3V9tx8MPY7XZxR8BAixS"); #[program] -pub mod blinkmart_protocol { +pub mod blinkmart_protocol { use super::*; - pub fn initialize(ctx: Context) -> Result<()> { - instructions::initialize(ctx) + pub fn initialize(ctx: Context, params: InitializeParams) -> Result<()> { + instructions::initialize(ctx, params) } pub fn listing(ctx: Context, params: ListingParams) -> Result<()> { diff --git a/programs/blinkmart-protocol/src/state/order.rs b/programs/blinkmart-protocol/src/state/order.rs index 65f6caa..88456fa 100644 --- a/programs/blinkmart-protocol/src/state/order.rs +++ b/programs/blinkmart-protocol/src/state/order.rs @@ -3,7 +3,7 @@ use anchor_lang::prelude::*; #[account] #[derive(InitSpace)] pub struct Order { - #[max_len(20)] + #[max_len(40)] pub order_id: String, pub payer: Pubkey, pub amount: u64, diff --git a/programs/blinkmart-protocol/src/state/product.rs b/programs/blinkmart-protocol/src/state/product.rs index f30bf5f..fc32343 100644 --- a/programs/blinkmart-protocol/src/state/product.rs +++ b/programs/blinkmart-protocol/src/state/product.rs @@ -3,7 +3,7 @@ use anchor_lang::prelude::*; #[account] #[derive(InitSpace)] pub struct Product { - #[max_len(40)] + #[max_len(32)] pub product_id: String, pub administrator: Pubkey, pub treasury: Pubkey, diff --git a/tests/blinkmart-protocol.ts b/tests/blinkmart-protocol.ts index 3f78759..2611e0b 100644 --- a/tests/blinkmart-protocol.ts +++ b/tests/blinkmart-protocol.ts @@ -1,16 +1,229 @@ import * as anchor from "@coral-xyz/anchor"; import { Program } from "@coral-xyz/anchor"; -import { BlinkmartProtocol } from "../target/types/blinkmart_protocol"; +import { BlinkmartProtocol } from "../app/src/idl/blinkmart_protocol"; +import { LAMPORTS_PER_SOL, sendAndConfirmTransaction } from "@solana/web3.js"; describe("blinkmart-protocol", () => { - // Configure the client to use the local cluster. - anchor.setProvider(anchor.AnchorProvider.env()); - + const provider = anchor.AnchorProvider.env(); + const connection = provider.connection; + anchor.setProvider(provider); + const authority = provider.wallet as anchor.Wallet; const program = anchor.workspace.BlinkmartProtocol as Program; - it("Is initialized!", async () => { - // Add your test here. - const tx = await program.methods.initialize().rpc(); - console.log("Your transaction signature", tx); + function logTx(txSignature) { + console.log(`\nTx: https://explorer.solana.com/tx/${txSignature}?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899`); + } + + function findPda(seeds: Array,) { + return anchor.web3.PublicKey.findProgramAddressSync(seeds, program.programId); + } + + async function airdrop(addr: anchor.web3.PublicKey) { + const airdropSignature = await connection.requestAirdrop(addr, LAMPORTS_PER_SOL * 10) + await connection.confirmTransaction(airdropSignature); + await sleep(2000) + console.log(addr.toBase58(), ": ", await connection.getBalance(addr, "confirmed")); + } + + async function execTx(tx, signers: anchor.web3.Signer[]) { + const txHash = await provider.sendAndConfirm(tx, signers) + logTx(txHash) + } + + function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + const [admin,] = findPda([Buffer.from("admin")]); + console.log("admin: ", admin.toBase58()); + + const administrator = anchor.web3.Keypair.generate(); + const treasury = anchor.web3.Keypair.generate() + const operation = anchor.web3.Keypair.generate() + const transactionFees = 500; // 5% + + it("Initialize", async () => { + await airdrop(administrator.publicKey) + await airdrop(treasury.publicKey) + await airdrop(operation.publicKey) + + const tx = await program.methods + .initialize({ + administrator: administrator.publicKey, + treasury: treasury.publicKey, + operation: operation.publicKey, + transactionFees: transactionFees + }) + .accountsPartial({ admin: admin, payer: administrator.publicKey }) + .transaction(); + const txs = new anchor.web3.Transaction().add(tx); + await execTx(txs, [administrator]) }); + + let productId = "e96d3d37-9850-467d-8574-7a534d7d13f7" // max length is 40\ + const productAdministrator = anchor.web3.Keypair.generate() + const productTreasury = anchor.web3.Keypair.generate() + const salesPrice = new anchor.BN(LAMPORTS_PER_SOL * 0.5) + // const inventory = new anchor.BN(100) + + // productId = anchor.utils.sha256.hash(productId) + // console.log("productId: ", productId.toString()); + // console.log("productId Buffer from: ", Buffer.from(productId)); + // console.log("productId Uint8Array from: ", Uint8Array.from(Buffer.from(productId).subarray(0, 8))); + // console.log(productId); + // return + productId = productId.slice(0, 31) + + const [product,] = findPda([Buffer.from("product"), Buffer.from(productId)]); + console.log("product: ", product.toBase58()); + console.log("productAdministrator: ", productAdministrator.publicKey.toBase58()); + console.log("productTreasury: ", productTreasury.publicKey.toBase58()); + + it("Listing", async () => { + await airdrop(productAdministrator.publicKey) + await airdrop(productTreasury.publicKey) + + const tx = await program.methods + .listing({ + productId: productId, + administrator: productAdministrator.publicKey, + treasury: productTreasury.publicKey, + salesPrice: salesPrice, + }) + .accountsPartial({ + authority: productAdministrator.publicKey, + product: product + }) + .instruction() + const txs = new anchor.web3.Transaction().add(tx); + await execTx(txs, [productAdministrator]) + }); + + + const customer = anchor.web3.Keypair.generate() + + let orderId = "e42faae5-622b-4d26-b3cc-5b41fec283da" // max length is 40 + orderId = orderId.slice(0, 31) + const [order,] = findPda([Buffer.from("order"), Buffer.from(orderId)]); + console.log("order: ", order.toBase58()); + const orderQuantity = new anchor.BN(2); + + + it("Customer buy something 1...", async () => { + await airdrop(customer.publicKey) + + const tx = await program.methods + .placeOrder({ + orderId: orderId, + productId: productId, + payer: customer.publicKey, + orderQuantity: orderQuantity + }) + .accountsPartial({ + product: product, + order: order, + admin: admin, + payer: customer.publicKey + }) + .instruction() + const txs = new anchor.web3.Transaction().add(tx); + await execTx(txs, [customer]) + }); + + + let orderId2 = "82cb1edd-fb72-4de6-81ed-74cc3116ecbe".slice(0, 31) // max length is 40 + const [order2,] = findPda([Buffer.from("order"), Buffer.from(orderId2)]); + console.log("order2: ", order2.toBase58()); + + + it("Customer buy something 2...", async () => { + const tx = await program.methods + .placeOrder({ + orderId: orderId2, + productId: productId, + payer: customer.publicKey, + orderQuantity: orderQuantity + }) + .accountsPartial({ + product: product, + order: order2, + admin: admin, + payer: customer.publicKey + }) + .instruction() + const txs = new anchor.web3.Transaction().add(tx); + await execTx(txs, [customer]) + }); + + + it("Customer confirm recepit", async () => { + const tx = await program.methods + .confirmReceipt({ + orderId: orderId, + productId: productId, + }) + .accountsPartial({ + payer: customer.publicKey, + product: product, + order: order, + admin: admin, + }) + .instruction() + const txs = new anchor.web3.Transaction().add(tx); + await execTx(txs, [customer]) + + }); + + + it("Seller withdraw all", async () => { + const tx = await program.methods + .sellerWithdraw({ + productId: productId, + }) + .accountsPartial({ + administrator: productAdministrator.publicKey, + treasury: productTreasury.publicKey, + product: product, + admin: admin, + }) + .instruction() + const txs = new anchor.web3.Transaction().add(tx); + await execTx(txs, [productAdministrator]) + + }); + + it("Customer return something...", async () => { + const tx = await program.methods + .cancelOrder({ + orderId: orderId2, + productId: productId, + }) + .accountsPartial({ + payer: customer.publicKey, + product: product, + order: order2, + admin: admin, + }) + .instruction() + const txs = new anchor.web3.Transaction().add(tx); + await execTx(txs, [customer]) + + }); + + it("Delisting", async () => { + const tx = await program.methods + .delisting({ + productId: productId, + }) + .accountsPartial({ + administrator: productAdministrator.publicKey, + treasury: productTreasury.publicKey, + product: product, + admin: admin, + }) + .instruction() + const txs = new anchor.web3.Transaction().add(tx); + await execTx(txs, [productAdministrator]) + }); + }); diff --git a/yarn.lock b/yarn.lock index 0b64a30..18c5307 100644 --- a/yarn.lock +++ b/yarn.lock @@ -55,14 +55,184 @@ resolved "https://registry.npmmirror.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== -"@solana/buffer-layout@^4.0.1": +"@solana/buffer-layout-utils@^0.2.0": + version "0.2.0" + resolved "https://registry.npmmirror.com/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz#b45a6cab3293a2eb7597cceb474f229889d875ca" + integrity sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g== + dependencies: + "@solana/buffer-layout" "^4.0.0" + "@solana/web3.js" "^1.32.0" + bigint-buffer "^1.1.5" + bignumber.js "^9.0.1" + +"@solana/buffer-layout@^4.0.0", "@solana/buffer-layout@^4.0.1": version "4.0.1" resolved "https://registry.npmmirror.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15" integrity sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA== dependencies: buffer "~6.0.3" -"@solana/web3.js@^1.68.0": +"@solana/codecs-core@2.0.0-preview.4": + version "2.0.0-preview.4" + resolved "https://registry.npmmirror.com/@solana/codecs-core/-/codecs-core-2.0.0-preview.4.tgz#770826105f2f884110a21662573e7a2014654324" + integrity sha512-A0VVuDDA5kNKZUinOqHxJQK32aKTucaVbvn31YenGzHX1gPqq+SOnFwgaEY6pq4XEopSmaK16w938ZQS8IvCnw== + dependencies: + "@solana/errors" "2.0.0-preview.4" + +"@solana/codecs-core@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.npmmirror.com/@solana/codecs-core/-/codecs-core-2.0.0-rc.1.tgz#1a2d76b9c7b9e7b7aeb3bd78be81c2ba21e3ce22" + integrity sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ== + dependencies: + "@solana/errors" "2.0.0-rc.1" + +"@solana/codecs-data-structures@2.0.0-preview.4": + version "2.0.0-preview.4" + resolved "https://registry.npmmirror.com/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-preview.4.tgz#f8a2470982a9792334737ea64000ccbdff287247" + integrity sha512-nt2k2eTeyzlI/ccutPcG36M/J8NAYfxBPI9h/nQjgJ+M+IgOKi31JV8StDDlG/1XvY0zyqugV3I0r3KAbZRJpA== + dependencies: + "@solana/codecs-core" "2.0.0-preview.4" + "@solana/codecs-numbers" "2.0.0-preview.4" + "@solana/errors" "2.0.0-preview.4" + +"@solana/codecs-data-structures@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.npmmirror.com/@solana/codecs-data-structures/-/codecs-data-structures-2.0.0-rc.1.tgz#d47b2363d99fb3d643f5677c97d64a812982b888" + integrity sha512-rinCv0RrAVJ9rE/rmaibWJQxMwC5lSaORSZuwjopSUE6T0nb/MVg6Z1siNCXhh/HFTOg0l8bNvZHgBcN/yvXog== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/codecs-numbers" "2.0.0-rc.1" + "@solana/errors" "2.0.0-rc.1" + +"@solana/codecs-numbers@2.0.0-preview.4": + version "2.0.0-preview.4" + resolved "https://registry.npmmirror.com/@solana/codecs-numbers/-/codecs-numbers-2.0.0-preview.4.tgz#6a53b456bb7866f252d8c032c81a92651e150f66" + integrity sha512-Q061rLtMadsO7uxpguT+Z7G4UHnjQ6moVIxAQxR58nLxDPCC7MB1Pk106/Z7NDhDLHTcd18uO6DZ7ajHZEn2XQ== + dependencies: + "@solana/codecs-core" "2.0.0-preview.4" + "@solana/errors" "2.0.0-preview.4" + +"@solana/codecs-numbers@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.npmmirror.com/@solana/codecs-numbers/-/codecs-numbers-2.0.0-rc.1.tgz#f34978ddf7ea4016af3aaed5f7577c1d9869a614" + integrity sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/errors" "2.0.0-rc.1" + +"@solana/codecs-strings@2.0.0-preview.4": + version "2.0.0-preview.4" + resolved "https://registry.npmmirror.com/@solana/codecs-strings/-/codecs-strings-2.0.0-preview.4.tgz#4d06bb722a55a5d04598d362021bfab4bd446760" + integrity sha512-YDbsQePRWm+xnrfS64losSGRg8Wb76cjK1K6qfR8LPmdwIC3787x9uW5/E4icl/k+9nwgbIRXZ65lpF+ucZUnw== + dependencies: + "@solana/codecs-core" "2.0.0-preview.4" + "@solana/codecs-numbers" "2.0.0-preview.4" + "@solana/errors" "2.0.0-preview.4" + +"@solana/codecs-strings@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.npmmirror.com/@solana/codecs-strings/-/codecs-strings-2.0.0-rc.1.tgz#e1d9167075b8c5b0b60849f8add69c0f24307018" + integrity sha512-9/wPhw8TbGRTt6mHC4Zz1RqOnuPTqq1Nb4EyuvpZ39GW6O2t2Q7Q0XxiB3+BdoEjwA2XgPw6e2iRfvYgqty44g== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/codecs-numbers" "2.0.0-rc.1" + "@solana/errors" "2.0.0-rc.1" + +"@solana/codecs@2.0.0-preview.4": + version "2.0.0-preview.4" + resolved "https://registry.npmmirror.com/@solana/codecs/-/codecs-2.0.0-preview.4.tgz#a1923cc78a6f64ebe656c7ec6335eb6b70405b22" + integrity sha512-gLMupqI4i+G4uPi2SGF/Tc1aXcviZF2ybC81x7Q/fARamNSgNOCUUoSCg9nWu1Gid6+UhA7LH80sWI8XjKaRog== + dependencies: + "@solana/codecs-core" "2.0.0-preview.4" + "@solana/codecs-data-structures" "2.0.0-preview.4" + "@solana/codecs-numbers" "2.0.0-preview.4" + "@solana/codecs-strings" "2.0.0-preview.4" + "@solana/options" "2.0.0-preview.4" + +"@solana/codecs@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.npmmirror.com/@solana/codecs/-/codecs-2.0.0-rc.1.tgz#146dc5db58bd3c28e04b4c805e6096c2d2a0a875" + integrity sha512-qxoR7VybNJixV51L0G1RD2boZTcxmwUWnKCaJJExQ5qNKwbpSyDdWfFJfM5JhGyKe9DnPVOZB+JHWXnpbZBqrQ== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/codecs-data-structures" "2.0.0-rc.1" + "@solana/codecs-numbers" "2.0.0-rc.1" + "@solana/codecs-strings" "2.0.0-rc.1" + "@solana/options" "2.0.0-rc.1" + +"@solana/errors@2.0.0-preview.4": + version "2.0.0-preview.4" + resolved "https://registry.npmmirror.com/@solana/errors/-/errors-2.0.0-preview.4.tgz#056ba76b6dd900dafa70117311bec3aef0f5250b" + integrity sha512-kadtlbRv2LCWr8A9V22On15Us7Nn8BvqNaOB4hXsTB3O0fU40D1ru2l+cReqLcRPij4znqlRzW9Xi0m6J5DIhA== + dependencies: + chalk "^5.3.0" + commander "^12.1.0" + +"@solana/errors@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.npmmirror.com/@solana/errors/-/errors-2.0.0-rc.1.tgz#3882120886eab98a37a595b85f81558861b29d62" + integrity sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ== + dependencies: + chalk "^5.3.0" + commander "^12.1.0" + +"@solana/options@2.0.0-preview.4": + version "2.0.0-preview.4" + resolved "https://registry.npmmirror.com/@solana/options/-/options-2.0.0-preview.4.tgz#212d35d1da87c7efb13de4d3569ad9eb070f013d" + integrity sha512-tv2O/Frxql/wSe3jbzi5nVicIWIus/BftH+5ZR+r9r3FO0/htEllZS5Q9XdbmSboHu+St87584JXeDx3xm4jaA== + dependencies: + "@solana/codecs-core" "2.0.0-preview.4" + "@solana/codecs-data-structures" "2.0.0-preview.4" + "@solana/codecs-numbers" "2.0.0-preview.4" + "@solana/codecs-strings" "2.0.0-preview.4" + "@solana/errors" "2.0.0-preview.4" + +"@solana/options@2.0.0-rc.1": + version "2.0.0-rc.1" + resolved "https://registry.npmmirror.com/@solana/options/-/options-2.0.0-rc.1.tgz#06924ba316dc85791fc46726a51403144a85fc4d" + integrity sha512-mLUcR9mZ3qfHlmMnREdIFPf9dpMc/Bl66tLSOOWxw4ml5xMT2ohFn7WGqoKcu/UHkT9CrC6+amEdqCNvUqI7AA== + dependencies: + "@solana/codecs-core" "2.0.0-rc.1" + "@solana/codecs-data-structures" "2.0.0-rc.1" + "@solana/codecs-numbers" "2.0.0-rc.1" + "@solana/codecs-strings" "2.0.0-rc.1" + "@solana/errors" "2.0.0-rc.1" + +"@solana/spl-token-group@^0.0.5": + version "0.0.5" + resolved "https://registry.npmmirror.com/@solana/spl-token-group/-/spl-token-group-0.0.5.tgz#f955dcca782031c85e862b2b46878d1bb02db6c2" + integrity sha512-CLJnWEcdoUBpQJfx9WEbX3h6nTdNiUzswfFdkABUik7HVwSNA98u5AYvBVK2H93d9PGMOHAak2lHW9xr+zAJGQ== + dependencies: + "@solana/codecs" "2.0.0-preview.4" + "@solana/spl-type-length-value" "0.1.0" + +"@solana/spl-token-metadata@^0.1.3": + version "0.1.5" + resolved "https://registry.npmmirror.com/@solana/spl-token-metadata/-/spl-token-metadata-0.1.5.tgz#91616470d6862ec6b762e6cfcf882b8a8a24b1e8" + integrity sha512-DSBlo7vjuLe/xvNn75OKKndDBkFxlqjLdWlq6rf40StnrhRn7TDntHGLZpry1cf3uzQFShqeLROGNPAJwvkPnA== + dependencies: + "@solana/codecs" "2.0.0-rc.1" + "@solana/spl-type-length-value" "0.1.0" + +"@solana/spl-token@^0.4.8": + version "0.4.8" + resolved "https://registry.npmmirror.com/@solana/spl-token/-/spl-token-0.4.8.tgz#a84e4131af957fa9fbd2727e5fc45dfbf9083586" + integrity sha512-RO0JD9vPRi4LsAbMUdNbDJ5/cv2z11MGhtAvFeRzT4+hAGE/FUzRi0tkkWtuCfSIU3twC6CtmAihRp/+XXjWsA== + dependencies: + "@solana/buffer-layout" "^4.0.0" + "@solana/buffer-layout-utils" "^0.2.0" + "@solana/spl-token-group" "^0.0.5" + "@solana/spl-token-metadata" "^0.1.3" + buffer "^6.0.3" + +"@solana/spl-type-length-value@0.1.0": + version "0.1.0" + resolved "https://registry.npmmirror.com/@solana/spl-type-length-value/-/spl-type-length-value-0.1.0.tgz#b5930cf6c6d8f50c7ff2a70463728a4637a2f26b" + integrity sha512-JBMGB0oR4lPttOZ5XiUGyvylwLQjt1CPJa6qQ5oM+MBCndfjz2TKKkw0eATlLLcYmq1jBVsNlJ2cD6ns2GR7lA== + dependencies: + buffer "^6.0.3" + +"@solana/web3.js@^1.32.0", "@solana/web3.js@^1.68.0", "@solana/web3.js@^1.95.3": version "1.95.3" resolved "https://registry.npmmirror.com/@solana/web3.js/-/web3.js-1.95.3.tgz#70b5f4d76823f56b5af6403da51125fffeb65ff3" integrity sha512-O6rPUN0w2fkNqx/Z3QJMB9L225Ex10PRDH8bTaIUPZXMPV0QP8ZpPvjQnXK+upUczlRgzHzd6SjKIha1p+I6og== @@ -234,6 +404,11 @@ bigint-buffer@^1.1.5: dependencies: bindings "^1.3.0" +bignumber.js@^9.0.1: + version "9.1.2" + resolved "https://registry.npmmirror.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" + integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== + binary-extensions@^2.0.0: version "2.3.0" resolved "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" @@ -338,6 +513,11 @@ chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^5.3.0: + version "5.3.0" + resolved "https://registry.npmmirror.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + check-error@^1.0.3: version "1.0.3" resolved "https://registry.npmmirror.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" @@ -381,6 +561,11 @@ color-name@~1.1.4: resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +commander@^12.1.0: + version "12.1.0" + resolved "https://registry.npmmirror.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + commander@^2.20.3: version "2.20.3" resolved "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"