From d5caa024cf09735d420d9bd1e5da224963a2e656 Mon Sep 17 00:00:00 2001 From: Oshioke Salaki Date: Sat, 10 Feb 2024 14:15:50 +0000 Subject: [PATCH 01/11] test: transfer of stake token to staking contract address --- src/bwc_staking_contract.cairo | 3 +- .../test_bwc_staking_contract.cairo | 31 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/bwc_staking_contract.cairo b/src/bwc_staking_contract.cairo index 8cc9d2d..794bee8 100644 --- a/src/bwc_staking_contract.cairo +++ b/src/bwc_staking_contract.cairo @@ -38,7 +38,7 @@ mod BWCStakingContract { staker: LegacyMap::, bwcerc20_token_address: ContractAddress, receipt_token_address: ContractAddress, - reward_token_address: ContractAddress + reward_token_address: ContractAddress, } ////////////////// @@ -170,6 +170,7 @@ mod BWCStakingContract { self.staker.read(get_caller_address()).amount } + // Function allows caller to withdraw their staked token and get rewarded // @amount: Amount of token to withdraw // @BWCERC20TokenAddr: Contract address of token to withdraw diff --git a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo index a4159b7..73fea1a 100644 --- a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo +++ b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo @@ -166,6 +166,35 @@ fn test_new_stake_detail_balance() { assert(stake_dispatcher.get_stake_balance() == (prev_stake + 6), Errors::WRONG_STAKE_BALANCE); } +#[test] +fn test_transfer_stake_token(){ + let (staking_contract_address, bwc_contract_address, receipt_contract_address, _) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let prev_stake_contract_balance = bwc_dispatcher.balance_of(staking_contract_address); + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + + assert(bwc_dispatcher.allowance(Account::user1(), staking_contract_address) == 4, Errors::INVALID_ALLOWANCE); + assert(bwc_dispatcher.balance_of(staking_contract_address) == prev_stake_contract_balance + 6, Errors::INVALID_BALANCE); + stop_prank(CheatTarget::One(staking_contract_address)); +} + @@ -204,4 +233,6 @@ mod Account { const AMOUNT_NOT_ALLOWED: felt252 = 'STAKE: Amount not allowed'; const WITHDRAW_AMOUNT_NOT_ALLOWED: felt252 = 'STAKE: Amount not allowed'; const WRONG_STAKE_BALANCE: felt252 = 'STAKE: Wrong stake balance'; + const INVALID_BALANCE: felt252 = 'Invalid balance'; + const INVALID_ALLOWANCE: felt252 = 'Invalid allowance'; } \ No newline at end of file From af61899ed04c80f4f9f40357607ddf72f2a81bd8 Mon Sep 17 00:00:00 2001 From: Oshioke Salaki Date: Sat, 10 Feb 2024 14:37:32 +0000 Subject: [PATCH 02/11] test: that receipt token was transfered to staker after staking --- .../test_bwc_staking_contract.cairo | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo index 73fea1a..60917c9 100644 --- a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo +++ b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo @@ -196,6 +196,36 @@ fn test_transfer_stake_token(){ } +#[test] +fn test_transfer_receipt_token(){ + let (staking_contract_address, bwc_contract_address, receipt_contract_address, _) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let prev_stake_contract_receipt_token_balance: u256 = receipt_dispatcher.balance_of(staking_contract_address); + let prev_staker_receipt_token_balance: u256 = receipt_dispatcher.balance_of(Account::user1()); + + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + assert(receipt_dispatcher.balance_of(Account::user1()) == prev_staker_receipt_token_balance + 6 , Errors::INVALID_BALANCE); + stop_prank(CheatTarget::One(staking_contract_address)); +} + + From e0cf073012f1c1e52013463cb8e81d015e9c8c8c Mon Sep 17 00:00:00 2001 From: Oshioke Salaki Date: Sat, 10 Feb 2024 14:46:51 +0000 Subject: [PATCH 03/11] test: withdraw should revert if withdraw amount is greater than staked amount --- src/bwc_staking_contract.cairo | 4 +-- .../test_bwc_staking_contract.cairo | 29 ++++++++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/bwc_staking_contract.cairo b/src/bwc_staking_contract.cairo index 794bee8..b093896 100644 --- a/src/bwc_staking_contract.cairo +++ b/src/bwc_staking_contract.cairo @@ -86,7 +86,7 @@ mod BWCStakingContract { const NOT_WITHDRAW_TIME: felt252 = 'STAKE: Not yet withdraw time'; const LOW_CONTRACT_BALANCE: felt252 = 'STAKE: Low contract balance'; const AMOUNT_NOT_ALLOWED: felt252 = 'STAKE: Amount not allowed'; - const WITHDRAW_AMOUNT_NOT_ALLOWED: felt252 = 'STAKE: Amount not allowed'; + const WITHDRAW_AMOUNT_NOT_ALLOWED: felt252 = 'Withdraw amount not allowed'; } #[constructor] @@ -196,7 +196,7 @@ mod BWCStakingContract { let stake_time = stake.time_staked; assert( - amount <= stake_amount, 'Withdraw amt > than stake amt' + amount <= stake_amount, Errors::WITHDRAW_AMOUNT_NOT_ALLOWED ); // Staker cannot withdraw more than staked amount assert(self.is_time_to_withdraw(stake_time), 'Not yet time to withdraw'); assert( diff --git a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo index 60917c9..a41f901 100644 --- a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo +++ b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo @@ -225,6 +225,32 @@ fn test_transfer_receipt_token(){ stop_prank(CheatTarget::One(staking_contract_address)); } +#[test] +#[should_panic(expected: ('Withdraw amount not allowed',))] +fn test_invalid_withdrawal_amount() { + let (staking_contract_address, bwc_contract_address, receipt_contract_address, _) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + stake_dispatcher.withdraw(30); +} @@ -261,8 +287,9 @@ mod Account { const NOT_WITHDRAW_TIME: felt252 = 'STAKE: Not yet withdraw time'; const LOW_CONTRACT_BALANCE: felt252 = 'STAKE: Low contract balance'; const AMOUNT_NOT_ALLOWED: felt252 = 'STAKE: Amount not allowed'; - const WITHDRAW_AMOUNT_NOT_ALLOWED: felt252 = 'STAKE: Amount not allowed'; + const WITHDRAW_AMOUNT_NOT_ALLOWED: felt252 = 'Withdraw amount not allowed'; const WRONG_STAKE_BALANCE: felt252 = 'STAKE: Wrong stake balance'; const INVALID_BALANCE: felt252 = 'Invalid balance'; const INVALID_ALLOWANCE: felt252 = 'Invalid allowance'; + } \ No newline at end of file From 3fa061b43e7758174cf86e729db5641473903627 Mon Sep 17 00:00:00 2001 From: Oshioke Salaki Date: Sat, 10 Feb 2024 15:11:03 +0000 Subject: [PATCH 04/11] test: withdraw fails when attempted before set withdraw time --- src/bwc_staking_contract.cairo | 3 +- .../test_bwc_staking_contract.cairo | 38 ++++++++++++++++--- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/bwc_staking_contract.cairo b/src/bwc_staking_contract.cairo index b093896..71bb3e5 100644 --- a/src/bwc_staking_contract.cairo +++ b/src/bwc_staking_contract.cairo @@ -77,6 +77,7 @@ mod BWCStakingContract { ///////////////// mod Errors { const INSUFFICIENT_FUND: felt252 = 'STAKE: Insufficient fund'; + const INVALID_WITHDRAW_TIME: felt252 = 'Not yet time to withdraw'; const INSUFFICIENT_BALANCE: felt252 = 'STAKE: Insufficient balance'; const ADDRESS_ZERO: felt252 = 'STAKE: Address zero'; const NOT_TOKEN_ADDRESS: felt252 = 'STAKE: Not token address'; @@ -198,7 +199,7 @@ mod BWCStakingContract { assert( amount <= stake_amount, Errors::WITHDRAW_AMOUNT_NOT_ALLOWED ); // Staker cannot withdraw more than staked amount - assert(self.is_time_to_withdraw(stake_time), 'Not yet time to withdraw'); + assert(self.is_time_to_withdraw(stake_time), Errors::INVALID_WITHDRAW_TIME); assert( reward_contract.balance_of(address_this) >= amount, 'Not enough reward token to send' diff --git a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo index a41f901..47c1dbe 100644 --- a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo +++ b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo @@ -4,13 +4,10 @@ use core::result::ResultTrait; use core::option::OptionTrait; use basic_staking_dapp::bwc_staking_contract::{IStake, BWCStakingContract, IStakeDispatcher}; use basic_staking_dapp::erc20_token::{IERC20, ERC20, IERC20Dispatcher}; -use starknet::ContractAddress; +use starknet::{ContractAddress, get_block_timestamp}; use starknet::contract_address::contract_address_const; use core::array::ArrayTrait; -use snforge_std::{declare, ContractClassTrait, fs::{FileTrait, read_txt}}; -use snforge_std::{start_prank, stop_prank, CheatTarget}; - -use snforge_std::PrintTrait; +use snforge_std::{declare, ContractClassTrait, fs::{FileTrait, read_txt}, start_prank, stop_prank, CheatTarget, start_warp, PrintTrait}; use core::traits::{Into, TryInto}; use starknet::syscalls::deploy_syscall; use starknet::SyscallResultTrait; @@ -253,6 +250,37 @@ fn test_invalid_withdrawal_amount() { } +#[test] +#[should_panic(expected: ('Not yet time to withdraw',))] +fn test_invalid_withdraw_time() { + let (staking_contract_address, bwc_contract_address, receipt_contract_address, reward_contract_address) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; + + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + stake_dispatcher.withdraw(5); +} + + + + From ffb73f4a61bd0d88b879eb57404bf50e1745891e Mon Sep 17 00:00:00 2001 From: Oshioke Salaki Date: Sat, 10 Feb 2024 15:13:55 +0000 Subject: [PATCH 05/11] test: withdraw fails when there is insuffient reward tokens --- .../test_bwc_staking_contract.cairo | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo index 47c1dbe..0248723 100644 --- a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo +++ b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo @@ -278,7 +278,34 @@ fn test_invalid_withdraw_time() { stake_dispatcher.withdraw(5); } +#[test] +#[should_panic(expected: ('Not enough reward token to send',))] +fn test_insufficient_reward_token() { + let (staking_contract_address, bwc_contract_address, receipt_contract_address, reward_contract_address) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; + + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + start_warp(CheatTarget::One(staking_contract_address), get_block_timestamp() + 240); + stake_dispatcher.withdraw(5); +} From 0f0222dd6817e35c91ccb5c3359fc714835aa828 Mon Sep 17 00:00:00 2001 From: Oshioke Salaki Date: Sat, 10 Feb 2024 15:25:44 +0000 Subject: [PATCH 06/11] test: that there is sufficient bwc token for withdrawal --- .../test_bwc_staking_contract.cairo | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo index 0248723..310bddd 100644 --- a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo +++ b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo @@ -307,6 +307,34 @@ fn test_insufficient_reward_token() { stake_dispatcher.withdraw(5); } +#[test] +fn test_sufficient_bwc_token_for_withdraw() { + let (staking_contract_address, bwc_contract_address, receipt_contract_address, reward_contract_address) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; + + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + start_warp(CheatTarget::One(staking_contract_address), get_block_timestamp() + 240); + assert(bwc_dispatcher.balance_of(staking_contract_address) >= 6, Errors::INVALID_BALANCE); +} + From cac7eb0707cb340b784c4e6f9fb3eaf3aab107c6 Mon Sep 17 00:00:00 2001 From: Oshioke Salaki Date: Sat, 10 Feb 2024 16:30:58 +0000 Subject: [PATCH 07/11] test: sufficient token allowance for withdrawal --- src/bwc_staking_contract.cairo | 1 + .../test_bwc_staking_contract.cairo | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/bwc_staking_contract.cairo b/src/bwc_staking_contract.cairo index 71bb3e5..dcc2f50 100644 --- a/src/bwc_staking_contract.cairo +++ b/src/bwc_staking_contract.cairo @@ -157,6 +157,7 @@ mod BWCStakingContract { // // Staker calls the approve function of receipt token contract and approves this contract to transfer out `amount` receipt from staker account // Reason for this is to allow this contract withdraw the receipt token before sending back stake tokens + // receipt_contract.approve(address_this, amount); self .emit( diff --git a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo index 310bddd..55ee21c 100644 --- a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo +++ b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo @@ -335,6 +335,34 @@ fn test_sufficient_bwc_token_for_withdraw() { assert(bwc_dispatcher.balance_of(staking_contract_address) >= 6, Errors::INVALID_BALANCE); } +#[test] +fn test_sufficient_receipt_token_allowance_for_withdraw() { + let (staking_contract_address, bwc_contract_address, receipt_contract_address, reward_contract_address) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; + + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + receipt_dispatcher.approve(staking_contract_address, 6); + assert(receipt_dispatcher.allowance(Account::user1(), staking_contract_address) <= 6, Errors::INSUFFICIENT_BALANCE); +} + From 61589fcb40fed6196f6faadb1c85df4276b81038 Mon Sep 17 00:00:00 2001 From: Oshioke Salaki Date: Sat, 10 Feb 2024 19:23:03 +0000 Subject: [PATCH 08/11] refac: test_sufficient_receipt_token_allowance_for_withdraw logic --- src/tests/bwc_staking_contract/nmmn | 36 ++++++++++++++++ .../test_bwc_staking_contract.cairo | 42 ++++++++++++++++++- 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/tests/bwc_staking_contract/nmmn diff --git a/src/tests/bwc_staking_contract/nmmn b/src/tests/bwc_staking_contract/nmmn new file mode 100644 index 0000000..694b7af --- /dev/null +++ b/src/tests/bwc_staking_contract/nmmn @@ -0,0 +1,36 @@ +#[test] +#[should_panic(expected: ('receipt tkn allowance too low',))] +fn test_insufficient_receipt_token_allowance_for_withdraw() { + let (staking_contract_address, bwc_contract_address, receipt_contract_address, reward_contract_address) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; + + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(reward_contract_address), Account::admin()); + reward_dispatcher.transfer(staking_contract_address, 50); + stop_prank(CheatTarget::One(reward_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + + start_warp(CheatTarget::One(staking_contract_address), get_block_timestamp() + 240); + stake_dispatcher.withdraw(6); + +} \ No newline at end of file diff --git a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo index 55ee21c..28fa90b 100644 --- a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo +++ b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo @@ -359,8 +359,48 @@ fn test_sufficient_receipt_token_allowance_for_withdraw() { start_prank(CheatTarget::One(staking_contract_address), Account::user1()); stake_dispatcher.stake(6); + + start_prank(CheatTarget::One(receipt_contract_address), Account::user1()); receipt_dispatcher.approve(staking_contract_address, 6); - assert(receipt_dispatcher.allowance(Account::user1(), staking_contract_address) <= 6, Errors::INSUFFICIENT_BALANCE); + assert(receipt_dispatcher.allowance(Account::user1(), staking_contract_address) >= 6, Errors::INSUFFICIENT_BALANCE); +} + + + + + + + +#[test] +fn test_stake() { + let (staking_contract_address, bwc_contract_address, receipt_contract_address, reward_contract_address) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; + + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + + + + start_warp(CheatTarget::One(staking_contract_address), get_block_timestamp() + 240); + stake_dispatcher.withdraw(5); + assert(stake_dispatcher.get_stake_balance() == 1, Errors::INVALID_BALANCE); } From 18a2303511a5a244d715ab1f50beb5f0552e811c Mon Sep 17 00:00:00 2001 From: Oshioke Salaki Date: Sat, 10 Feb 2024 19:27:20 +0000 Subject: [PATCH 09/11] test: withdraw revert when there is insufficient receipt token allowance --- src/tests/bwc_staking_contract/nmmn | 36 ------------------ .../test_bwc_staking_contract.cairo | 37 +++++++++++++++++++ 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/tests/bwc_staking_contract/nmmn b/src/tests/bwc_staking_contract/nmmn index 694b7af..e69de29 100644 --- a/src/tests/bwc_staking_contract/nmmn +++ b/src/tests/bwc_staking_contract/nmmn @@ -1,36 +0,0 @@ -#[test] -#[should_panic(expected: ('receipt tkn allowance too low',))] -fn test_insufficient_receipt_token_allowance_for_withdraw() { - let (staking_contract_address, bwc_contract_address, receipt_contract_address, reward_contract_address) = - deploy_contract(); - let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; - let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; - let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; - let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; - - - start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); - bwc_dispatcher.transfer(Account::user1(), 35); - stop_prank(CheatTarget::One(bwc_contract_address)); - - start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); - receipt_dispatcher.transfer(staking_contract_address, 20); - stop_prank(CheatTarget::One(receipt_contract_address)); - - start_prank(CheatTarget::One(reward_contract_address), Account::admin()); - reward_dispatcher.transfer(staking_contract_address, 50); - stop_prank(CheatTarget::One(reward_contract_address)); - - start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); - bwc_dispatcher.approve(staking_contract_address, 10); - stop_prank(CheatTarget::One(bwc_contract_address)); - - - - start_prank(CheatTarget::One(staking_contract_address), Account::user1()); - stake_dispatcher.stake(6); - - start_warp(CheatTarget::One(staking_contract_address), get_block_timestamp() + 240); - stake_dispatcher.withdraw(6); - -} \ No newline at end of file diff --git a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo index 28fa90b..a62cec4 100644 --- a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo +++ b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo @@ -365,6 +365,43 @@ fn test_sufficient_receipt_token_allowance_for_withdraw() { assert(receipt_dispatcher.allowance(Account::user1(), staking_contract_address) >= 6, Errors::INSUFFICIENT_BALANCE); } +#[test] +#[should_panic(expected: ('receipt tkn allowance too low',))] +fn test_insufficient_receipt_token_allowance_for_withdraw() { + let (staking_contract_address, bwc_contract_address, receipt_contract_address, reward_contract_address) = + deploy_contract(); + let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; + let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; + let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; + let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; + + + start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); + bwc_dispatcher.transfer(Account::user1(), 35); + stop_prank(CheatTarget::One(bwc_contract_address)); + + start_prank(CheatTarget::One(receipt_contract_address), Account::admin()); + receipt_dispatcher.transfer(staking_contract_address, 20); + stop_prank(CheatTarget::One(receipt_contract_address)); + + start_prank(CheatTarget::One(reward_contract_address), Account::admin()); + reward_dispatcher.transfer(staking_contract_address, 50); + stop_prank(CheatTarget::One(reward_contract_address)); + + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); + bwc_dispatcher.approve(staking_contract_address, 10); + stop_prank(CheatTarget::One(bwc_contract_address)); + + + + start_prank(CheatTarget::One(staking_contract_address), Account::user1()); + stake_dispatcher.stake(6); + + start_warp(CheatTarget::One(staking_contract_address), get_block_timestamp() + 240); + stake_dispatcher.withdraw(6); + +} + From e1c19ce417b02f227fbf6d62d3211940191a8e33 Mon Sep 17 00:00:00 2001 From: Oshioke Salaki Date: Sat, 10 Feb 2024 19:51:36 +0000 Subject: [PATCH 10/11] test: withdraw function --- src/bwc_staking_contract.cairo | 2 +- .../test_bwc_staking_contract.cairo | 164 +++++++++++------- 2 files changed, 106 insertions(+), 60 deletions(-) diff --git a/src/bwc_staking_contract.cairo b/src/bwc_staking_contract.cairo index dcc2f50..5eff986 100644 --- a/src/bwc_staking_contract.cairo +++ b/src/bwc_staking_contract.cairo @@ -87,7 +87,7 @@ mod BWCStakingContract { const NOT_WITHDRAW_TIME: felt252 = 'STAKE: Not yet withdraw time'; const LOW_CONTRACT_BALANCE: felt252 = 'STAKE: Low contract balance'; const AMOUNT_NOT_ALLOWED: felt252 = 'STAKE: Amount not allowed'; - const WITHDRAW_AMOUNT_NOT_ALLOWED: felt252 = 'Withdraw amount not allowed'; + const WITHDRAW_AMOUNT_NOT_ALLOWED: felt252 = 'Withdraw amount not allowed'; } #[constructor] diff --git a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo index a62cec4..6abf845 100644 --- a/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo +++ b/src/tests/bwc_staking_contract/test_bwc_staking_contract.cairo @@ -7,7 +7,10 @@ use basic_staking_dapp::erc20_token::{IERC20, ERC20, IERC20Dispatcher}; use starknet::{ContractAddress, get_block_timestamp}; use starknet::contract_address::contract_address_const; use core::array::ArrayTrait; -use snforge_std::{declare, ContractClassTrait, fs::{FileTrait, read_txt}, start_prank, stop_prank, CheatTarget, start_warp, PrintTrait}; +use snforge_std::{ + declare, ContractClassTrait, fs::{FileTrait, read_txt}, start_prank, stop_prank, CheatTarget, + start_warp, PrintTrait +}; use core::traits::{Into, TryInto}; use starknet::syscalls::deploy_syscall; use starknet::SyscallResultTrait; @@ -164,7 +167,7 @@ fn test_new_stake_detail_balance() { } #[test] -fn test_transfer_stake_token(){ +fn test_transfer_stake_token() { let (staking_contract_address, bwc_contract_address, receipt_contract_address, _) = deploy_contract(); let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; @@ -186,24 +189,30 @@ fn test_transfer_stake_token(){ start_prank(CheatTarget::One(staking_contract_address), Account::user1()); stake_dispatcher.stake(6); - - assert(bwc_dispatcher.allowance(Account::user1(), staking_contract_address) == 4, Errors::INVALID_ALLOWANCE); - assert(bwc_dispatcher.balance_of(staking_contract_address) == prev_stake_contract_balance + 6, Errors::INVALID_BALANCE); + + assert( + bwc_dispatcher.allowance(Account::user1(), staking_contract_address) == 4, + Errors::INVALID_ALLOWANCE + ); + assert( + bwc_dispatcher.balance_of(staking_contract_address) == prev_stake_contract_balance + 6, + Errors::INVALID_BALANCE + ); stop_prank(CheatTarget::One(staking_contract_address)); } #[test] -fn test_transfer_receipt_token(){ +fn test_transfer_receipt_token() { let (staking_contract_address, bwc_contract_address, receipt_contract_address, _) = deploy_contract(); let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; - let prev_stake_contract_receipt_token_balance: u256 = receipt_dispatcher.balance_of(staking_contract_address); + let prev_stake_contract_receipt_token_balance: u256 = receipt_dispatcher + .balance_of(staking_contract_address); let prev_staker_receipt_token_balance: u256 = receipt_dispatcher.balance_of(Account::user1()); - start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); bwc_dispatcher.transfer(Account::user1(), 35); stop_prank(CheatTarget::One(bwc_contract_address)); @@ -218,7 +227,10 @@ fn test_transfer_receipt_token(){ start_prank(CheatTarget::One(staking_contract_address), Account::user1()); stake_dispatcher.stake(6); - assert(receipt_dispatcher.balance_of(Account::user1()) == prev_staker_receipt_token_balance + 6 , Errors::INVALID_BALANCE); + assert( + receipt_dispatcher.balance_of(Account::user1()) == prev_staker_receipt_token_balance + 6, + Errors::INVALID_BALANCE + ); stop_prank(CheatTarget::One(staking_contract_address)); } @@ -231,7 +243,6 @@ fn test_invalid_withdrawal_amount() { let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; - start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); bwc_dispatcher.transfer(Account::user1(), 35); stop_prank(CheatTarget::One(bwc_contract_address)); @@ -253,14 +264,18 @@ fn test_invalid_withdrawal_amount() { #[test] #[should_panic(expected: ('Not yet time to withdraw',))] fn test_invalid_withdraw_time() { - let (staking_contract_address, bwc_contract_address, receipt_contract_address, reward_contract_address) = + let ( + staking_contract_address, + bwc_contract_address, + receipt_contract_address, + reward_contract_address + ) = deploy_contract(); let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; - start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); bwc_dispatcher.transfer(Account::user1(), 35); stop_prank(CheatTarget::One(bwc_contract_address)); @@ -281,14 +296,18 @@ fn test_invalid_withdraw_time() { #[test] #[should_panic(expected: ('Not enough reward token to send',))] fn test_insufficient_reward_token() { - let (staking_contract_address, bwc_contract_address, receipt_contract_address, reward_contract_address) = + let ( + staking_contract_address, + bwc_contract_address, + receipt_contract_address, + reward_contract_address + ) = deploy_contract(); let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; - start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); bwc_dispatcher.transfer(Account::user1(), 35); stop_prank(CheatTarget::One(bwc_contract_address)); @@ -309,14 +328,18 @@ fn test_insufficient_reward_token() { #[test] fn test_sufficient_bwc_token_for_withdraw() { - let (staking_contract_address, bwc_contract_address, receipt_contract_address, reward_contract_address) = + let ( + staking_contract_address, + bwc_contract_address, + receipt_contract_address, + reward_contract_address + ) = deploy_contract(); let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; - start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); bwc_dispatcher.transfer(Account::user1(), 35); stop_prank(CheatTarget::One(bwc_contract_address)); @@ -337,14 +360,18 @@ fn test_sufficient_bwc_token_for_withdraw() { #[test] fn test_sufficient_receipt_token_allowance_for_withdraw() { - let (staking_contract_address, bwc_contract_address, receipt_contract_address, reward_contract_address) = + let ( + staking_contract_address, + bwc_contract_address, + receipt_contract_address, + reward_contract_address + ) = deploy_contract(); let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; - start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); bwc_dispatcher.transfer(Account::user1(), 35); stop_prank(CheatTarget::One(bwc_contract_address)); @@ -362,20 +389,27 @@ fn test_sufficient_receipt_token_allowance_for_withdraw() { start_prank(CheatTarget::One(receipt_contract_address), Account::user1()); receipt_dispatcher.approve(staking_contract_address, 6); - assert(receipt_dispatcher.allowance(Account::user1(), staking_contract_address) >= 6, Errors::INSUFFICIENT_BALANCE); + assert( + receipt_dispatcher.allowance(Account::user1(), staking_contract_address) >= 6, + Errors::INSUFFICIENT_BALANCE + ); } #[test] #[should_panic(expected: ('receipt tkn allowance too low',))] fn test_insufficient_receipt_token_allowance_for_withdraw() { - let (staking_contract_address, bwc_contract_address, receipt_contract_address, reward_contract_address) = + let ( + staking_contract_address, + bwc_contract_address, + receipt_contract_address, + reward_contract_address + ) = deploy_contract(); let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; - start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); bwc_dispatcher.transfer(Account::user1(), 35); stop_prank(CheatTarget::One(bwc_contract_address)); @@ -384,7 +418,7 @@ fn test_insufficient_receipt_token_allowance_for_withdraw() { receipt_dispatcher.transfer(staking_contract_address, 20); stop_prank(CheatTarget::One(receipt_contract_address)); - start_prank(CheatTarget::One(reward_contract_address), Account::admin()); + start_prank(CheatTarget::One(reward_contract_address), Account::admin()); reward_dispatcher.transfer(staking_contract_address, 50); stop_prank(CheatTarget::One(reward_contract_address)); @@ -392,32 +426,28 @@ fn test_insufficient_receipt_token_allowance_for_withdraw() { bwc_dispatcher.approve(staking_contract_address, 10); stop_prank(CheatTarget::One(bwc_contract_address)); - - start_prank(CheatTarget::One(staking_contract_address), Account::user1()); stake_dispatcher.stake(6); - start_warp(CheatTarget::One(staking_contract_address), get_block_timestamp() + 240); - stake_dispatcher.withdraw(6); - + start_warp(CheatTarget::One(staking_contract_address), get_block_timestamp() + 240); + stake_dispatcher.withdraw(6); } - - - - - #[test] -fn test_stake() { - let (staking_contract_address, bwc_contract_address, receipt_contract_address, reward_contract_address) = +fn test_withdraw() { + let ( + staking_contract_address, + bwc_contract_address, + receipt_contract_address, + reward_contract_address + ) = deploy_contract(); let receipt_dispatcher = IERC20Dispatcher { contract_address: receipt_contract_address }; let stake_dispatcher = IStakeDispatcher { contract_address: staking_contract_address }; let bwc_dispatcher = IERC20Dispatcher { contract_address: bwc_contract_address }; let reward_dispatcher = IERC20Dispatcher { contract_address: reward_contract_address }; - start_prank(CheatTarget::One(bwc_contract_address), Account::admin()); bwc_dispatcher.transfer(Account::user1(), 35); stop_prank(CheatTarget::One(bwc_contract_address)); @@ -426,6 +456,10 @@ fn test_stake() { receipt_dispatcher.transfer(staking_contract_address, 20); stop_prank(CheatTarget::One(receipt_contract_address)); + start_prank(CheatTarget::One(reward_contract_address), Account::admin()); + reward_dispatcher.transfer(staking_contract_address, 50); + stop_prank(CheatTarget::One(reward_contract_address)); + start_prank(CheatTarget::One(bwc_contract_address), Account::user1()); bwc_dispatcher.approve(staking_contract_address, 10); stop_prank(CheatTarget::One(bwc_contract_address)); @@ -433,15 +467,28 @@ fn test_stake() { start_prank(CheatTarget::One(staking_contract_address), Account::user1()); stake_dispatcher.stake(6); - + start_prank(CheatTarget::One(receipt_contract_address), Account::user1()); + receipt_dispatcher.approve(staking_contract_address, 6); + stop_prank(CheatTarget::One(receipt_contract_address)); start_warp(CheatTarget::One(staking_contract_address), get_block_timestamp() + 240); - stake_dispatcher.withdraw(5); - assert(stake_dispatcher.get_stake_balance() == 1, Errors::INVALID_BALANCE); -} + stake_dispatcher.withdraw(6); + + // Test that staker stake balance has been updated + assert(stake_dispatcher.get_stake_balance() == 0, Errors::INVALID_BALANCE); + // Test that receipt tokens have removed from staker balance + assert(receipt_dispatcher.balance_of(Account::user1()) == 0, Errors::INVALID_BALANCE); + // Test that reciept tokens have been returned to staking contract + assert(receipt_dispatcher.balance_of(staking_contract_address) == 20, Errors::INVALID_BALANCE); + // Test that reward token has been sent to the staker + assert(reward_dispatcher.balance_of(Account::user1()) == 6, Errors::INVALID_BALANCE); + + // Test that stake token has been sent to the staker + assert(bwc_dispatcher.balance_of(Account::user1()) == 35, Errors::INVALID_BALANCE); +} mod Account { @@ -461,23 +508,22 @@ mod Account { } - ///////////////// - //CUSTOM ERRORS - ///////////////// - mod Errors { - const INSUFFICIENT_FUND: felt252 = 'STAKE: Insufficient fund'; - const INSUFFICIENT_BALANCE: felt252 = 'STAKE: Insufficient balance'; - const ADDRESS_ZERO: felt252 = 'STAKE: Address zero'; - const NOT_TOKEN_ADDRESS: felt252 = 'STAKE: Not token address'; - const ZERO_AMOUNT: felt252 = 'STAKE: Zero amount'; - const INSUFFICIENT_FUNDS: felt252 = 'STAKE: Insufficient funds'; - const LOW_CBWCRT_BALANCE: felt252 = 'STAKE: Low balance'; - const NOT_WITHDRAW_TIME: felt252 = 'STAKE: Not yet withdraw time'; - const LOW_CONTRACT_BALANCE: felt252 = 'STAKE: Low contract balance'; - const AMOUNT_NOT_ALLOWED: felt252 = 'STAKE: Amount not allowed'; - const WITHDRAW_AMOUNT_NOT_ALLOWED: felt252 = 'Withdraw amount not allowed'; - const WRONG_STAKE_BALANCE: felt252 = 'STAKE: Wrong stake balance'; - const INVALID_BALANCE: felt252 = 'Invalid balance'; - const INVALID_ALLOWANCE: felt252 = 'Invalid allowance'; - - } \ No newline at end of file +///////////////// +//CUSTOM ERRORS +///////////////// +mod Errors { + const INSUFFICIENT_FUND: felt252 = 'STAKE: Insufficient fund'; + const INSUFFICIENT_BALANCE: felt252 = 'STAKE: Insufficient balance'; + const ADDRESS_ZERO: felt252 = 'STAKE: Address zero'; + const NOT_TOKEN_ADDRESS: felt252 = 'STAKE: Not token address'; + const ZERO_AMOUNT: felt252 = 'STAKE: Zero amount'; + const INSUFFICIENT_FUNDS: felt252 = 'STAKE: Insufficient funds'; + const LOW_CBWCRT_BALANCE: felt252 = 'STAKE: Low balance'; + const NOT_WITHDRAW_TIME: felt252 = 'STAKE: Not yet withdraw time'; + const LOW_CONTRACT_BALANCE: felt252 = 'STAKE: Low contract balance'; + const AMOUNT_NOT_ALLOWED: felt252 = 'STAKE: Amount not allowed'; + const WITHDRAW_AMOUNT_NOT_ALLOWED: felt252 = 'Withdraw amount not allowed'; + const WRONG_STAKE_BALANCE: felt252 = 'STAKE: Wrong stake balance'; + const INVALID_BALANCE: felt252 = 'Invalid balance'; + const INVALID_ALLOWANCE: felt252 = 'Invalid allowance'; +} From 070d2122785f21cf500da5f3f1a05a4796feef79 Mon Sep 17 00:00:00 2001 From: Oshioke Salaki Date: Sat, 10 Feb 2024 20:39:52 +0000 Subject: [PATCH 11/11] refac: gitignore --- dapp/.gitignore | 1 + .../@parcel/watcher-wasm/README.md | 135 -- .../@parcel/watcher-wasm/index.d.ts | 51 - .../@parcel/watcher-wasm/index.mjs | 326 ---- .../node_modules/napi-wasm/README.md | 100 -- .../node_modules/napi-wasm/index.js | 1374 ----------------- .../node_modules/napi-wasm/index.mjs | 1371 ---------------- .../node_modules/napi-wasm/package.json | 33 - .../@parcel/watcher-wasm/package.json | 38 - .../@parcel/watcher-wasm/watcher.wasm | Bin 110770 -> 0 bytes .../@parcel/watcher-wasm/wrapper.js | 77 - src/tests/bwc_staking_contract/nmmn | 0 12 files changed, 1 insertion(+), 3505 deletions(-) create mode 100644 dapp/.gitignore delete mode 100644 dapp/node_modules/@parcel/watcher-wasm/README.md delete mode 100644 dapp/node_modules/@parcel/watcher-wasm/index.d.ts delete mode 100644 dapp/node_modules/@parcel/watcher-wasm/index.mjs delete mode 100644 dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/README.md delete mode 100644 dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/index.js delete mode 100644 dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/index.mjs delete mode 100644 dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/package.json delete mode 100644 dapp/node_modules/@parcel/watcher-wasm/package.json delete mode 100644 dapp/node_modules/@parcel/watcher-wasm/watcher.wasm delete mode 100644 dapp/node_modules/@parcel/watcher-wasm/wrapper.js delete mode 100644 src/tests/bwc_staking_contract/nmmn diff --git a/dapp/.gitignore b/dapp/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/dapp/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/dapp/node_modules/@parcel/watcher-wasm/README.md b/dapp/node_modules/@parcel/watcher-wasm/README.md deleted file mode 100644 index 5c34150..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/README.md +++ /dev/null @@ -1,135 +0,0 @@ -# @parcel/watcher - -A native C++ Node module for querying and subscribing to filesystem events. Used by [Parcel 2](https://github.com/parcel-bundler/parcel). - -## Features - -- **Watch** - subscribe to realtime recursive directory change notifications when files or directories are created, updated, or deleted. -- **Query** - performantly query for historical change events in a directory, even when your program is not running. -- **Native** - implemented in C++ for performance and low-level integration with the operating system. -- **Cross platform** - includes backends for macOS, Linux, Windows, FreeBSD, and Watchman. -- **Performant** - events are throttled in C++ so the JavaScript thread is not overwhelmed during large filesystem changes (e.g. `git checkout` or `npm install`). -- **Scalable** - tens of thousands of files can be watched or queried at once with good performance. - -## Example - -```javascript -const watcher = require('@parcel/watcher'); -const path = require('path'); - -// Subscribe to events -let subscription = await watcher.subscribe(process.cwd(), (err, events) => { - console.log(events); -}); - -// later on... -await subscription.unsubscribe(); - -// Get events since some saved snapshot in the past -let snapshotPath = path.join(process.cwd(), 'snapshot.txt'); -let events = await watcher.getEventsSince(process.cwd(), snapshotPath); - -// Save a snapshot for later -await watcher.writeSnapshot(process.cwd(), snapshotPath); -``` - -## Watching - -`@parcel/watcher` supports subscribing to realtime notifications of changes in a directory. It works recursively, so changes in sub-directories will also be emitted. - -Events are throttled and coalesced for performance during large changes like `git checkout` or `npm install`, and a single notification will be emitted with all of the events at the end. - -Only one notification will be emitted per file. For example, if a file was both created and updated since the last event, you'll get only a `create` event. If a file is both created and deleted, you will not be notifed of that file. Renames cause two events: a `delete` for the old name, and a `create` for the new name. - -```javascript -let subscription = await watcher.subscribe(process.cwd(), (err, events) => { - console.log(events); -}); -``` - -Events have two properties: - -- `type` - the event type: `create`, `update`, or `delete`. -- `path` - the absolute path to the file or directory. - -To unsubscribe from change notifications, call the `unsubscribe` method on the returned subscription object. - -```javascript -await subscription.unsubscribe(); -``` - -`@parcel/watcher` has the following watcher backends, listed in priority order: - -- [FSEvents](https://developer.apple.com/documentation/coreservices/file_system_events) on macOS -- [Watchman](https://facebook.github.io/watchman/) if installed -- [inotify](http://man7.org/linux/man-pages/man7/inotify.7.html) on Linux -- [ReadDirectoryChangesW](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v%3Dvs.85%29.aspx) on Windows -- [kqueue](https://man.freebsd.org/cgi/man.cgi?kqueue) on FreeBSD, or as an alternative to FSEvents on macOS - -You can specify the exact backend you wish to use by passing the `backend` option. If that backend is not available on the current platform, the default backend will be used instead. See below for the list of backend names that can be passed to the options. - -## Querying - -`@parcel/watcher` also supports querying for historical changes made in a directory, even when your program is not running. This makes it easy to invalidate a cache and re-build only the files that have changed, for example. It can be **significantly** faster than traversing the entire filesystem to determine what files changed, depending on the platform. - -In order to query for historical changes, you first need a previous snapshot to compare to. This can be saved to a file with the `writeSnapshot` function, e.g. just before your program exits. - -```javascript -await watcher.writeSnapshot(dirPath, snapshotPath); -``` - -When your program starts up, you can query for changes that have occurred since that snapshot using the `getEventsSince` function. - -```javascript -let events = await watcher.getEventsSince(dirPath, snapshotPath); -``` - -The events returned are exactly the same as the events that would be passed to the `subscribe` callback (see above). - -`@parcel/watcher` has the following watcher backends, listed in priority order: - -- [FSEvents](https://developer.apple.com/documentation/coreservices/file_system_events) on macOS -- [Watchman](https://facebook.github.io/watchman/) if installed -- [fts](http://man7.org/linux/man-pages/man3/fts.3.html) (brute force) on Linux and FreeBSD -- [FindFirstFile](https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-findfirstfilea) (brute force) on Windows - -The FSEvents (macOS) and Watchman backends are significantly more performant than the brute force backends used by default on Linux and Windows, for example returning results in miliseconds instead of seconds for large directory trees. This is because a background daemon monitoring filesystem changes on those platforms allows us to query cached data rather than traversing the filesystem manually (brute force). - -macOS has good performance with FSEvents by default. For the best performance on other platforms, install [Watchman](https://facebook.github.io/watchman/) and it will be used by `@parcel/watcher` automatically. - -You can specify the exact backend you wish to use by passing the `backend` option. If that backend is not available on the current platform, the default backend will be used instead. See below for the list of backend names that can be passed to the options. - -## Options - -All of the APIs in `@parcel/watcher` support the following options, which are passed as an object as the last function argument. - -- `ignore` - an array of paths or glob patterns to ignore. uses [`is-glob`](https://github.com/micromatch/is-glob) to distinguish paths from globs. glob patterns are parsed with [`micromatch`](https://github.com/micromatch/micromatch) (see [features](https://github.com/micromatch/micromatch#matching-features)). - - paths can be relative or absolute and can either be files or directories. No events will be emitted about these files or directories or their children. - - glob patterns match on relative paths from the root that is watched. No events will be emitted for matching paths. -- `backend` - the name of an explicitly chosen backend to use. Allowed options are `"fs-events"`, `"watchman"`, `"inotify"`, `"kqueue"`, `"windows"`, or `"brute-force"` (only for querying). If the specified backend is not available on the current platform, the default backend will be used instead. - -## WASM - -The `@parcel/watcher-wasm` package can be used in place of `@parcel/watcher` on unsupported platforms. It relies on the Node `fs` module, so in non-Node environments such as browsers, an `fs` polyfill will be needed. The `@parcel/watcher-wasm` package is published as an ESM-only module. - -**Note**: the WASM implementation is significantly less efficient than the native implementations because it must crawl the file system to watch each directory individually. Use the native `@parcel/watcher` package wherever possible. - -```js -import {subscribe} from '@parcel/watcher-wasm'; - -// Use the module as documented above. -subscribe(/* ... */); -``` - -## Who is using this? - -- [Parcel 2](https://parceljs.org/) -- [VSCode](https://code.visualstudio.com/updates/v1_62#_file-watching-changes) -- [Tailwind CSS Intellisense](https://github.com/tailwindlabs/tailwindcss-intellisense) -- [Gatsby Cloud](https://twitter.com/chatsidhartha/status/1435647412828196867) -- [Nx](https://nx.dev) -- [Nuxt](https://nuxt.com) - -## License - -MIT diff --git a/dapp/node_modules/@parcel/watcher-wasm/index.d.ts b/dapp/node_modules/@parcel/watcher-wasm/index.d.ts deleted file mode 100644 index 8f70382..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/index.d.ts +++ /dev/null @@ -1,51 +0,0 @@ -declare type FilePath = string; -declare type GlobPattern = string; - -declare namespace ParcelWatcher { - export type BackendType = - | 'fs-events' - | 'watchman' - | 'inotify' - | 'windows' - | 'brute-force'; - export type EventType = 'create' | 'update' | 'delete'; - export interface Options { - ignore?: (FilePath|GlobPattern)[]; - backend?: BackendType; - } - export type SubscribeCallback = ( - err: Error | null, - events: Event[] - ) => unknown; - export interface AsyncSubscription { - unsubscribe(): Promise; - } - export interface Event { - path: FilePath; - type: EventType; - } - export function getEventsSince( - dir: FilePath, - snapshot: FilePath, - opts?: Options - ): Promise; - export function subscribe( - dir: FilePath, - fn: SubscribeCallback, - opts?: Options - ): Promise; - export function unsubscribe( - dir: FilePath, - fn: SubscribeCallback, - opts?: Options - ): Promise; - export function writeSnapshot( - dir: FilePath, - snapshot: FilePath, - opts?: Options - ): Promise; -} - -export = ParcelWatcher; -/** Initializes the web assembly module. */ -export default function init(input?: string | URL | Request): Promise; diff --git a/dapp/node_modules/@parcel/watcher-wasm/index.mjs b/dapp/node_modules/@parcel/watcher-wasm/index.mjs deleted file mode 100644 index e4fd052..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/index.mjs +++ /dev/null @@ -1,326 +0,0 @@ -import { Environment, napi } from 'napi-wasm'; -import fs from 'fs'; -import Path from 'path'; -import { createWrapper } from './wrapper.js'; - -let env; -let encoder = new TextEncoder; - -let constants = { - O_ACCMODE: 0o00000003, - O_RDONLY: 0, - O_WRONLY: 0o00000001, - O_RDWR: 0o00000002, - O_CREAT: 0o00000100, - O_EXCL: 0o00000200, - O_NOCTTY: 0o00000400, - O_TRUNC: 0o00001000, - O_APPEND: 0o00002000, - O_NONBLOCK: 0o00004000, - O_SYNC: 0o00010000, - FASYNC: 0o00020000, - O_DIRECT: 0o00040000, - O_LARGEFILE: 0o00100000, - O_DIRECTORY: 0o00200000, - O_NOFOLLOW: 0o00400000, - O_NOATIME: 0o01000000, - O_CLOEXEC: 0o02000000 -}; - -napi.napi_get_last_error_info = () => {}; - -const fds = new Map(); -const dirs = new Map(); -const regexCache = new Map(); -const watches = [null]; - -const wasm_env = { - __syscall_newfstatat(dirfd, path, buf, flags) { - let dir = dirfd === -100 ? process.cwd() : fds.get(dirfd).path; - let p = Path.resolve(dir, env.getString(path)); - let nofollow = flags & 256; - try { - let stat = nofollow ? fs.lstatSync(p, {bigint: true}) : fs.statSync(p, {bigint: true}); - return writeStat(stat, buf); - } catch (err) { - env.i32[env.instance.exports.__errno_location >> 2] = err.errno; - return -1; - } - }, - __syscall_lstat64(path, buf) { - let p = env.getString(path); - try { - let stat = fs.lstatSync(p, {bigint: true}); - return writeStat(stat, buf); - } catch (err) { - env.i32[env.instance.exports.__errno_location >> 2] = err.errno; - return -1; - } - }, - __syscall_fstat64(fd, buf) { - try { - let stat = fs.fstatSync(fd, {bigint: true}); - return writeStat(stat, buf); - } catch (err) { - env.i32[env.instance.exports.__errno_location >> 2] = err.errno; - return -1; - } - }, - __syscall_stat64(path, buf) { - let p = env.getString(path); - try { - let stat = fs.statSync(p, {bigint: true}); - return writeStat(stat, buf); - } catch (err) { - env.i32[env.instance.exports.__errno_location >> 2] = err.errno; - return -1; - } - }, - __syscall_getdents64(fd, dirp, count) { - let p = fds.get(fd).path; - let dir = dirs.get(fd); - let entries = dir?.entries; - if (!entries) { - try { - entries = fs.readdirSync(p, {withFileTypes: true}); - } catch (err) { - env.i32[env.instance.exports.__errno_location >> 2] = err.errno; - return -1; - } - } - - let start = dirp; - let i = dir?.index || 0; - for (; i < entries.length; i++) { - let entry = entries[i]; - let type = entry.isFIFO() ? 1 - : entry.isCharacterDevice() ? 2 - : entry.isDirectory() ? 4 - : entry.isBlockDevice() ? 6 - : entry.isFile() ? 8 - : entry.isSymbolicLink() ? 10 - : entry.isSocket() ? 12 - : 0; - let len = align(utf8Length(entry.name) + 20, 8); - if ((dirp - start + len) > count) { - break; - } - - // Write a linux_dirent64 struct into wasm memory. - env.u64[dirp >> 3] = 1n; // ino - env.u64[(dirp + 8) >> 3] = BigInt((dirp - start) + len); // offset - env.u16[(dirp + 16) >> 1] = len; - env.memory[dirp + 18] = type; - let {written} = encoder.encodeInto(entry.name, env.memory.subarray(dirp + 19)); - env.memory[dirp + 19 + written] = 0; // null terminate - dirp += len; - } - - dirs.set(fd, {index: i, entries}); - return dirp - start; - }, - __syscall_openat(dirfd, path, flags, mode) { - // Convert flags to Node values. - let f = 0; - for (let c in constants) { - if (flags & constants[c]) { - f |= fs.constants[c] || 0; - } - } - let dir = dirfd === -100 ? process.cwd() : fds.get(dirfd)?.path; - if (!dir) { - env.i32[env.instance.exports.__errno_location >> 2] = 9970; // ENOTDIR - return -1; - } - let p = Path.resolve(dir, env.getString(path)); - try { - let fd = fs.openSync(p, f); - fds.set(fd, {path: p, flags}); - return fd; - } catch (err) { - env.i32[env.instance.exports.__errno_location >> 2] = err.errno; - return -1; - } - }, - __syscall_fcntl64(fd, cmd) { - switch (cmd) { - case 3: - return fds.get(fd).flags; - case 2: - return 0; - default: - throw new Error('Unknown fcntl64 call: ' + cmd); - } - }, - __syscall_ioctl() {}, - emscripten_resize_heap() { - return 0; - }, - abort() {}, - wasm_backend_add_watch(filename, backend) { - let path = env.getString(filename); - let watch = fs.watch(path, {encoding: 'buffer'}, (eventType, filename) => { - if (filename) { - let type = eventType === 'change' ? 1 : 2; - let fptr = env.instance.exports.malloc(filename.byteLength + 1); - env.memory.set(filename, fptr); - env.memory[fptr + filename.byteLength] = 0; - env.instance.exports.wasm_backend_event_handler(backend, wd, type, fptr); - env.instance.exports.free(fptr); - } - }); - - let wd = watches.length; - watches.push(watch); - return wd; - }, - wasm_backend_remove_watch(wd) { - watches[wd].close(); - watches[wd] = undefined; - }, - set_timeout(ms, ctx) { - return setTimeout(() => { - env.instance.exports.on_timeout(ctx); - }, ms); - }, - clear_timeout(t) { - clearTimeout(t); - }, - emscripten_date_now() { - return Date.now(); - }, - _emscripten_get_now_is_monotonic() { - return true; - }, - emscripten_get_now() { - return performance.now(); - }, - wasm_regex_match(string, regex) { - let re = regexCache.get(regex); - if (!re) { - re = new RegExp(env.getString(regex)); - regexCache.set(regex, re); - } - return re.test(env.getString(string)) ? 1 : 0; - } -}; - -const wasi = { - fd_close(fd) { - fs.closeSync(fd); - fds.delete(fd); - dirs.delete(fd); - return 0; - }, - fd_seek(fd, offset_low, offset_high, whence, newOffset) { - return 0; - }, - fd_write(fd, iov, iovcnt, pnum) { - let buffers = []; - for (let i = 0; i < iovcnt; i++) { - let ptr = env.u32[iov >> 2]; - let len = env.u32[(iov + 4) >> 2]; - iov += 8; - if (len > 0) { - buffers.push(env.memory.subarray(ptr, ptr + len)); - } - } - let wrote = fs.writevSync(fd, buffers); - env.u32[pnum >> 2] = wrote; - return 0; - }, - fd_read(fd, iov, iovcnt, pnum) { - let buffers = []; - for (let i = 0; i < iovcnt; i++) { - let ptr = env.u32[iov >> 2]; - let len = env.u32[(iov + 4) >> 2]; - iov += 8; - if (len > 0) { - buffers.push(env.memory.subarray(ptr, ptr + len)); - } - } - - let read = fs.readvSync(fd, buffers); - env.u32[pnum >> 2] = read; - return 0; - } -}; - -function writeStat(stat, buf) { - env.i32[buf >> 2] = Number(stat.dev); - env.i32[(buf + 4) >> 2] = Number(stat.mode); - env.u32[(buf + 8) >> 2] = Number(stat.nlink); - env.i32[(buf + 12) >> 2] = Number(stat.uid); - env.i32[(buf + 16) >> 2] = Number(stat.gid); - env.i32[(buf + 20) >> 2] = Number(stat.rdev); - env.u64[(buf + 24) >> 3] = stat.size; - env.i32[(buf + 32) >> 2] = Number(stat.blksize); - env.i32[(buf + 36) >> 2] = Number(stat.blocks); - env.u64[(buf + 40) >> 3] = stat.atimeMs; - env.u32[(buf + 48) >> 2] = Number(stat.atimeNs); - env.u64[(buf + 56) >> 3] = stat.mtimeMs; - env.u32[(buf + 64) >> 2] = Number(stat.mtimeNs); - env.u64[(buf + 72) >> 3] = stat.ctimeMs; - env.u32[(buf + 80) >> 2] = Number(stat.ctimeNs); - env.u64[(buf + 88) >> 3] = stat.ino; - return 0; -} - -function utf8Length(string) { - let len = 0; - for (let i = 0; i < string.length; i++) { - let c = string.charCodeAt(i); - - if (c >= 0xd800 && c <= 0xdbff && i < string.length - 1) { - let c2 = string.charCodeAt(++i); - if ((c2 & 0xfc00) === 0xdc00) { - c = ((c & 0x3ff) << 10) + (c2 & 0x3ff) + 0x10000; - } else { - // unmatched surrogate. - i--; - } - } - - if ((c & 0xffffff80) === 0) { - len++; - } else if ((c & 0xfffff800) === 0) { - len += 2; - } else if ((c & 0xffff0000) === 0) { - len += 3; - } else if ((c & 0xffe00000) === 0) { - len += 4; - } - } - return len; -} - -function align(len, p) { - return Math.ceil(len / p) * p; -} - -let wasmBytes = fs.readFileSync(new URL('watcher.wasm', import.meta.url)); -let wasmModule = new WebAssembly.Module(wasmBytes); -let instance = new WebAssembly.Instance(wasmModule, { - napi, - env: wasm_env, - wasi_snapshot_preview1: wasi -}); - -env = new Environment(instance); -let wrapper = createWrapper(env.exports); - -export function writeSnapshot(dir, snapshot, opts) { - return wrapper.writeSnapshot(dir, snapshot, opts); -} - -export function getEventsSince(dir, snapshot, opts) { - return wrapper.getEventsSince(dir, snapshot, opts); -} - -export function subscribe(dir, fn, opts) { - return wrapper.subscribe(dir, fn, opts); -} - -export function unsubscribe(dir, fn, opts) { - return wrapper.unsubscribe(dir, fn, opts); -} diff --git a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/README.md b/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/README.md deleted file mode 100644 index ca23160..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/README.md +++ /dev/null @@ -1,100 +0,0 @@ -# napi-wasm - -An implementation of the [napi](https://nodejs.org/api/n-api.html) API for WASM. Enables using some native Node modules in browsers and other environments. - -## Setup - -To use napi-wasm, there are a few requirements: - -1. Configure your linker to export an indirect function table. With ldd, this is the `--export-table` flag. This enables JavaScript to call callback functions registered by WASM. It is exposed in the WebAssembly exports as `__indirect_function_table`. -2. Export a function from your WASM build named `napi_register_module_v1` (Node's default), or `napi_register_wasm_v1` for WASM-specific builds. This is called during initialization to setup the `exports` object for your module. It receives an environment and an exports object pointer as arguments, which you can add properties to. -3. Include a function named `napi_wasm_malloc` in your WASM build. This is called from JavaScript by napi-wasm to allocate memory in the WASM heap. It should accept a `uint32` size argument indicating the number of bytes to allocate, and return a `uint8` pointer to allocated memory. -4. Compile for the `wasm32-unknown-unknown` target. - -### In Rust - -The above steps should apply for any programming language, but here's an example in Rust. First, define a `napi_wasm_malloc` function so JavaScript can allocate memory in the WASM heap using the default allocator. - -```rust -use std::alloc::{alloc, Layout}; - -#[no_mangle] -pub extern "C" fn napi_wasm_malloc(size: usize) -> *mut u8 { - let align = std::mem::align_of::(); - if let Ok(layout) = Layout::from_size_align(size, align) { - unsafe { - if layout.size() > 0 { - let ptr = alloc(layout); - if !ptr.is_null() { - return ptr; - } - } else { - return align as *mut u8; - } - } - } - - std::process::abort(); -} -``` - -Next, implement `napi_register_wasm_v1` to register your module exports. We'll use the [napi-rs](https://github.com/napi-rs/napi-rs) bindings in this example to make it a bit nicer than calling C APIs directly. Note that the napi-rs `#[module_exports]` macro currently doesn't work in WASM because Rust doesn't support ctor setup functions in WASM targets yet, so we'll need to do this manually. - -```rust -use napi::{Env, JsObject, NapiValue}; - -#[no_mangle] -pub unsafe extern "C" fn napi_register_wasm_v1(raw_env: napi::sys::napi_env, raw_exports: napi::sys::napi_value) { - let env = Env::from_raw(raw_env); - let exports = JsObject::from_raw_unchecked(raw_env, raw_exports); - - exports.create_named_method("transform", transform); -} - -#[js_function(1)] -fn transform(ctx: CallContext) -> napi::Result { - // ... -} -``` - -To compile, you need to export a function table and use the correct target. - -```shell - RUSTFLAGS="-C link-arg=--export-table" cargo build --target wasm32-unknown-unknown -``` - -This will output a file in `target/wasm32-unknown-unknown/debug/YOUR_CRATE.wasm` which you can load in a JavaScript environment. - -You can also put the rust flags in a `.cargo/config.toml` file so you don't need to provide the environment variable each time you run `cargo build`. - -```toml -[target.wasm32-unknown-unknown] -rustflags = ["-C", "link-arg=--export-table"] -``` - -### Loading - -To load a WASM file and initialize a napi environment, you'll need to import the `napi-wasm` package. You instantiate a WASM module as usual, providing `napi` as the `env` import key. This provides the napi functions for your WASM module to use. - -Then, pass the WASM instance to the `Environment` constructor to setup a napi environment. This will call `napi_register_wasm_v1` or `napi_register_module_v1` to setup the exports object. Then you can call functions on the exports object as you would in Node. - -```js -import { Environment, napi } from 'napi-wasm'; - -// Construct a URL and instantiate a WebAssembly module as usual. -const url = new URL('path/to/lib.wasm', import.meta.url); -const { instance } = await WebAssembly.instantiateStreaming(fetch(url), { - env: napi -}); - -// Create an environment. -let env = new Environment(instance); -let exports = env.exports; - -// Use exports as usual! -exports.transform({ - // ... -}); -``` - -When you are done with an `Environment`, call the `destroy()` function to clean up memory. diff --git a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/index.js b/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/index.js deleted file mode 100644 index 6f6e6d9..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/index.js +++ /dev/null @@ -1,1374 +0,0 @@ -const NAPI_OK = 0; -const NAPI_GENERIC_FAILURE = 9; -const NAPI_PENDING_EXCEPTION = 10; -const NAPI_CANCELED = 11; -const NAPI_HANDLE_SCOPE_MISMATCH = 13; -const NAPI_NO_EXTERNAL_BUFFERS_ALLOWED = 22; - -// https://nodejs.org/api/n-api.html#napi_property_attributes -const NAPI_WRITABLE = 1 << 0; -const NAPI_ENUMERABLE = 1 << 1; -const NAPI_CONFIGURABLE = 1 << 2; -const NAPI_STATIC = 1 << 10; - -// https://nodejs.org/api/n-api.html#napi_typedarray_type -const typedArrays = [ - Int8Array, - Uint8Array, - Uint8ClampedArray, - Int16Array, - Uint16Array, - Int32Array, - Uint32Array, - Float32Array, - Float64Array, - BigInt64Array, - BigUint64Array -]; - -const environments = []; - -class Environment { - scopes = []; - referenceId = 1; - references = new Map(); - deferred = [null]; - wrappedObjects = new WeakMap(); - externalObjects = new WeakMap(); - buffers = new Map(); - instanceData = 0; - pendingException = null; - - constructor(instance) { - this.id = environments.length; - environments.push(this); - - this.instance = instance; - this.table = instance.exports.__indirect_function_table; - this.exports = {}; - - this.pushScope(); - let values = this.scopes[this.scopes.length - 1]; - let exports = values.length; - values.push(this.exports); - - try { - if (this.instance.exports.napi_register_module_v1) { - this.instance.exports.napi_register_module_v1(this.id, exports); - } - - if (this.instance.exports.napi_register_wasm_v1) { - this.instance.exports.napi_register_wasm_v1(this.id, exports); - } - } finally { - this.popScope(); - if (this.pendingException) { - let e = this.pendingException; - this.pendingException = null; - throw e; - } - } - } - - destroy() { - environments[this.id] = undefined; - } - - getString(ptr, len = strlen(this.memory, ptr)) { - return decoder.decode(this.memory.subarray(ptr, Math.max(0, ptr + len))); - } - - pushScope() { - let id = this.scopes.length; - this.scopes.push(id ? [...this.scopes[id - 1]] : [undefined, null, globalThis, true, false]); - return id; - } - - popScope() { - this.scopes.pop(); - - // Update any buffers with values which might have been modified in WASM copy. - for (let [buffer, slice] of this.buffers) { - // Ignore if buffer or slice has been detached. - if (buffer.byteLength && slice.byteLength) { - buffer.set(slice); - } - } - - this.buffers.clear(); - } - - get(idx) { - return this.scopes[this.scopes.length - 1][idx]; - } - - set(idx, value) { - this.scopes[this.scopes.length - 1][idx] = value; - } - - pushValue(value, scope = this.scopes.length - 1) { - let values = this.scopes[scope]; - let id = values.length; - values.push(value); - return id; - } - - createValue(value, result, scope) { - if (typeof value === 'boolean') { - this.setPointer(result, value ? 3 : 4); - return NAPI_OK; - } else if (typeof value === 'undefined') { - this.setPointer(result, 0); - return NAPI_OK; - } else if (value === null) { - this.setPointer(result, 1); - return NAPI_OK; - } else if (value === globalThis) { - this.setPointer(result, 2); - return NAPI_OK; - } - - let id = this.pushValue(value, scope); - this.setPointer(result, id); - return NAPI_OK; - } - - setPointer(ptr, value) { - this.u32[ptr >> 2] = value; - return NAPI_OK; - } - - _u32 = new Uint32Array(); - get u32() { - if (this._u32.byteLength === 0) { - this._u32 = new Uint32Array(this.instance.exports.memory.buffer); - } - - return this._u32; - } - - _i32 = new Int32Array(); - get i32() { - if (this._i32.byteLength === 0) { - this._i32 = new Int32Array(this.instance.exports.memory.buffer); - } - - return this._i32; - } - - _u16 = new Uint16Array(); - get u16() { - if (this._u16.byteLength === 0) { - this._u16 = new Uint16Array(this.instance.exports.memory.buffer); - } - - return this._u16; - } - - _u64 = new BigUint64Array(); - get u64() { - if (this._u64.byteLength === 0) { - this._u64 = new BigUint64Array(this.instance.exports.memory.buffer); - } - - return this._u64; - } - - _i64 = new BigInt64Array(); - get i64() { - if (this._i64.byteLength === 0) { - this._i64 = new BigInt64Array(this.instance.exports.memory.buffer); - } - - return this._i64; - } - - _f64 = new Float64Array(); - get f64() { - if (this._f64.byteLength === 0) { - this._f64 = new Float64Array(this.instance.exports.memory.buffer); - } - - return this._f64; - } - - _buf = new Uint8Array(); - get memory() { - if (this._buf.byteLength === 0) { - this._buf = new Uint8Array(this.instance.exports.memory.buffer); - } - - return this._buf; - } - - getBufferInfo(buf, ptr) { - if (this.buffers.has(buf)) { - let b = this.buffers.get(buf); - this.setPointer(ptr, b.byteOffset); - return b.byteLength; - } - - if (buf instanceof ArrayBuffer) { - let b = this.copyBuffer(new Uint8Array(buf)); - this.setPointer(ptr, b.byteOffset); - return b.byteLength; - } - - // If this is a view into WASM memory, no copies needed. - if (buf.buffer === this.instance.exports.memory.buffer) { - this.setPointer(ptr, buf.byteOffset); - return buf.byteLength; - } - - let b = this.copyBuffer(new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength)); - this.setPointer(ptr, b.byteOffset); - return b.byteLength; - } - - copyBuffer(data) { - let ptr = this.instance.exports.napi_wasm_malloc(data.byteLength); - let mem = this.memory; - mem.set(data, ptr); - let buf = mem.subarray(ptr, ptr + data.byteLength); - this.buffers.set(data, buf); - return buf; - } - - createFunction(cb, data) { - let env = this; - let fn = env.table.get(cb); - let func = function (...args) { - let scope = env.pushScope(); - - try { - let values = env.scopes[scope]; - let info = values.length; - values.push({ - thisArg: this, - args, - data, - newTarget: new.target - }); - - let res = fn(env.id, info); - return env.get(res); - } finally { - env.popScope(); - if (env.pendingException) { - let e = env.pendingException; - env.pendingException = null; - throw e; - } - } - }; - - return func; - } - - readPropertyDescriptor(ptr) { - // https://nodejs.org/api/n-api.html#napi_property_descriptor - let buf = this.u32; - let utf8name = buf[ptr++]; - let nameValue = buf[ptr++]; - let method = buf[ptr++]; - let getter = buf[ptr++]; - let setter = buf[ptr++]; - let val = buf[ptr++]; - let attrs = buf[ptr++]; - let data = buf[ptr++]; - - let name = utf8name ? this.getString(utf8name) : this.get(nameValue); - let writable = Boolean(attrs & NAPI_WRITABLE); - let enumerable = Boolean(attrs & NAPI_ENUMERABLE); - let configurable = Boolean(attrs & NAPI_CONFIGURABLE); - let isStatic = Boolean(attrs & NAPI_STATIC); - let get = getter ? this.createFunction(getter, data) : undefined; - let set = setter ? this.createFunction(setter, data) : undefined; - let value = method ? this.createFunction(method, data) : val ? this.get(val) : undefined; - - let descriptor = { - name, - static: isStatic, - configurable, - enumerable - }; - if (get || set) { - descriptor.get = get; - descriptor.set = set; - } else if (value) { - descriptor.writable = writable; - descriptor.value = value; - } - - return descriptor; - } -} - -const decoder = new TextDecoder("utf-8", { ignoreBOM: true, fatal: true }); -const latin1Decoder = new TextDecoder('latin1'); -const utf16Decoder = new TextDecoder('utf-16'); -const encoder = new TextEncoder(); - -class FinalizeRecord { - constructor(env, finalize, hint, data) { - this.env = env; - this.finalize = finalize; - this.hint = hint; - this.data = data; - } -} - -const finalizationRegistry = new FinalizationRegistry(buffer => { - if (buffer.finalize) { - buffer.finalize(buffer.env, buffer.data, buffer.hint); - } -}); - -class ExternalValue {} - -const threadsafeFunctions = []; - -class ThreadSafeFunction { - constructor(env, fn, nativeFn, context) { - this.env = env; - this.fn = fn; - this.nativeFn = nativeFn; - this.context = context; - this.id = threadsafeFunctions.length; - threadsafeFunctions.push(this); - } -} - -const asyncWork = [null]; - -class AsyncWork { - constructor(env, execute, complete, data) { - this.env = env; - this.execute = execute; - this.complete = complete; - this.data = data; - this.id = asyncWork.length; - asyncWork.push(this); - } -} - -const napi = { - napi_open_handle_scope(env_id, result) { - let env = environments[env_id]; - let id = env.pushScope(); - return env.setPointer(result, id); - }, - napi_close_handle_scope(env_id, scope) { - let env = environments[env_id]; - if (scope !== env.scopes.length - 1) { - return NAPI_HANDLE_SCOPE_MISMATCH; - } - env.popScope(); - return NAPI_OK; - }, - napi_open_escapable_handle_scope(env_id, result) { - let env = environments[env_id]; - let id = env.pushScope(); - return env.setPointer(result, id); - }, - napi_close_escapable_handle_scope(env_id, scope) { - let env = environments[env_id]; - if (scope !== env.scopes.length - 1) { - return NAPI_HANDLE_SCOPE_MISMATCH; - } - env.popScope(); - return NAPI_OK; - }, - napi_escape_handle(env_id, scope_id, escapee, result) { - let env = environments[env_id]; - let value = env.get(escapee); - // Create a value in the outer scope. - return env.createValue(value, result, scope_id - 1); - }, - napi_create_object(env_id, result) { - let env = environments[env_id]; - return env.createValue({}, result); - }, - napi_set_property(env_id, object, key, value) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - let val = env.get(value); - obj[name] = val; - return NAPI_OK; - }, - napi_get_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - return env.createValue(obj[name], result); - }, - napi_delete_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - let res = false; - try { - res = delete obj[name]; - } catch (err) {} - if (result) { - env.memory[result] = res ? 1 : 0; - } - return NAPI_OK; - }, - napi_has_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - // return env.setPointer(result, name in obj ? 1 : 0); - env.memory[result] = name in obj ? 1 : 0; - return NAPI_OK; - }, - napi_has_own_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - env.memory[result] = obj.hasOwnProperty(name) ? 1 : 0; - return NAPI_OK; - }, - napi_set_named_property(env_id, object, utf8Name, value) { - let env = environments[env_id]; - let obj = env.get(object); - let val = env.get(value); - let name = env.getString(utf8Name); - obj[name] = val; - return NAPI_OK; - }, - napi_get_named_property(env_id, object, utf8Name, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.getString(utf8Name); - return env.createValue(obj[name], result); - }, - napi_has_named_property(env_id, object, utf8Name, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.getString(utf8Name); - env.memory[result] = name in obj ? 1 : 0; - return NAPI_OK; - }, - napi_get_property_names(env_id, object, result) { - let env = environments[env_id]; - let obj = env.get(object); - let properties = Object.keys(obj); - return env.createValue(properties, result); - }, - napi_get_all_property_names(env_id, object, key_mode, key_filter, key_conversion, result) { - throw new Error('not implemented'); - }, - napi_define_properties(env_id, object, property_count, properties) { - let env = environments[env_id]; - let obj = env.get(object); - let ptr = properties >> 2; - for (let i = 0; i < property_count; i++) { - let descriptor = env.readPropertyDescriptor(ptr); - Object.defineProperty(obj, descriptor.name, descriptor); - ptr += 8; - } - return NAPI_OK; - }, - napi_object_freeze(env_id, object) { - let env = environments[env_id]; - let obj = env.get(object); - Object.freeze(obj); - return NAPI_OK; - }, - napi_object_seal(env_id, object) { - let env = environments[env_id]; - let obj = env.get(object); - Object.seal(obj); - return NAPI_OK; - }, - napi_get_prototype(env_id, object, result) { - let env = environments[env_id]; - let obj = env.get(object); - return env.createValue(Object.getPrototypeOf(obj), result); - }, - napi_define_class(env_id, utf8name, length, constructor, data, property_count, properties, result) { - let env = environments[env_id]; - let func = env.createFunction(constructor, data); - - Object.defineProperty(func, 'name', { - value: env.getString(utf8name, length), - configurable: true - }); - - let ptr = properties >> 2; - for (let i = 0; i < property_count; i++) { - let descriptor = env.readPropertyDescriptor(ptr); - if (descriptor.static) { - Object.defineProperty(func, descriptor.name, descriptor); - } else { - Object.defineProperty(func.prototype, descriptor.name, descriptor); - } - ptr += 8; - } - - return env.createValue(func, result); - }, - napi_create_reference(env_id, value, refcount, result) { - let env = environments[env_id]; - let id = env.referenceId++; - env.references.set(id, { - value: env.get(value), - refcount - }); - return env.setPointer(result, id); - }, - napi_delete_reference(env_id, ref) { - let env = environments[env_id]; - env.references.delete(ref); - return NAPI_OK; - }, - napi_get_reference_value(env_id, ref, result) { - let env = environments[env_id]; - let reference = env.references.get(ref); - return env.createValue(reference.value, result); - }, - napi_reference_ref(env_id, ref, result) { - let env = environments[env_id]; - let reference = env.references.get(ref); - reference.refcount++; - return env.setPointer(result, reference.refcount); - }, - napi_reference_unref(env_id, ref, result) { - let env = environments[env_id]; - let reference = env.references.get(ref); - if (reference.refcount === 0) { - return NAPI_GENERIC_FAILURE; - } - reference.refcount--; - return env.setPointer(result, reference.refcount); - }, - napi_add_env_cleanup_hook() { - return NAPI_OK; - }, - napi_remove_env_cleanup_hook() { - return NAPI_OK; - }, - napi_add_async_cleanup_hook() { - return NAPI_OK; - }, - napi_remove_async_cleanup_hook() { - return NAPI_OK; - }, - napi_set_instance_data(env_id, data, finalize_cb, finalize_hint) { - let env = environments[env_id]; - env.instanceData = data; - return NAPI_OK; - }, - napi_get_instance_data(env_id, data) { - let env = environments[env_id]; - return env.setPointer(data, env.instanceData); - }, - napi_get_boolean(env_id, value, result) { - let env = environments[env_id]; - return env.setPointer(result, value ? 3 : 4); - }, - napi_get_value_bool(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val ? 1 : 0; - return NAPI_OK; - }, - napi_create_int32(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(value, result); - }, - napi_get_value_int32(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.i32[result >> 2] = val; - return NAPI_OK; - }, - napi_create_uint32(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(value, result); - }, - napi_get_value_uint32(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - return env.setPointer(result, val); - }, - napi_create_int64(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Number(value), result); - }, - napi_get_value_int64(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.i64[result >> 3] = val; - return NAPI_OK; - }, - napi_create_double(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(value, result); - }, - napi_get_value_double(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.f64[result >> 3] = val; - return NAPI_OK; - }, - napi_create_bigint_int64(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(BigInt.asIntN(64, value), result); - }, - napi_get_value_bigint_int64(env_id, value, result, lossless) { - let env = environments[env_id]; - let val = env.get(value); - env.i64[result >> 3] = val; - if (lossless) { - env.memory[lossless] = BigInt.asIntN(64, val) === val ? 1 : 0; - } - return NAPI_OK; - }, - napi_create_bigint_uint64(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(BigInt.asUintN(64, value), result); - }, - napi_get_value_bigint_uint64(env_id, value, result, lossless) { - let env = environments[env_id]; - let val = env.get(value); - env.u64[result >> 3] = val; - if (lossless) { - env.memory[lossless] = BigInt.asUintN(64, val) === val ? 1 : 0; - } - return NAPI_OK; - }, - napi_create_bigint_words(env_id, sign_bit, word_count, words, result) { - let env = environments[env_id]; - let buf = env.u64; - let ptr = words >> 3; - let res = 0n; - let shift = 0n; - - for (let i = 0; i < word_count; i++) { - let word = buf[ptr++]; - res += word << shift; - shift += 64n; - } - - res *= BigInt((-1) ** sign_bit); - return env.createValue(res, result); - }, - napi_get_value_bigint_words(env_id, value, sign_bit, word_count, words) { - let env = environments[env_id]; - let val = env.get(value); - let count = env.u32[word_count >> 2]; - - if (sign_bit) { - env.i32[sign_bit] = val < 0n ? 1 : 0; - } - - let i = 0; - if (words) { - let mask = (1n << 64n) - 1n; - let buf = env.u64; - let ptr = words >> 3; - if (val < 0n) { - val = -val; - } - - for (; i < count && val !== 0n; i++) { - buf[ptr++] = val & mask; - val >>= 64n; - } - } - - while (val > 0n) { - i++; - val >>= 64n; - } - - return env.setPointer(word_count, i); - }, - napi_get_null(env_id, result) { - let env = environments[env_id]; - return env.setPointer(result, 1); - }, - napi_create_array(env_id, result) { - let env = environments[env_id]; - return env.createValue([], result); - }, - napi_create_array_with_length(env_id, length, result) { - let env = environments[env_id]; - return env.createValue(new Array(length), result); - }, - napi_set_element(env_id, object, index, value) { - let env = environments[env_id]; - let obj = env.get(object); - let val = env.get(value); - obj[index] = val; - return NAPI_OK; - }, - napi_get_element(env_id, object, index, result) { - let env = environments[env_id]; - let obj = env.get(object); - let val = obj[index]; - return env.createValue(val, result); - }, - napi_has_element(env_id, object, index, result) { - let env = environments[env_id]; - let obj = env.get(object); - env.memory[result] = obj.hasOwnProperty(index) ? 1 : 0; - return NAPI_OK; - }, - napi_delete_element(env_id, object, index, result) { - let env = environments[env_id]; - let obj = env.get(object); - let res = false; - try { - res = delete obj[index]; - } catch (err) {} - if (result) { - env.memory[result] = res ? 1 : 0; - } - return NAPI_OK; - }, - napi_get_array_length(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - return env.setPointer(result, val.length); - }, - napi_get_undefined(env_id, result) { - let env = environments[env_id]; - return env.setPointer(result, 0); - }, - napi_create_function(env_id, utf8name, length, cb, data, result) { - let env = environments[env_id]; - let func = env.createFunction(cb, data); - - Object.defineProperty(func, 'name', { - value: env.getString(utf8name, length), - configurable: true - }); - - return env.createValue(func, result); - }, - napi_call_function(env_id, recv, func, argc, argv, result) { - let env = environments[env_id]; - let thisArg = env.get(recv); - let fn = env.get(func); - let args = new Array(argc); - let mem = env.u32; - for (let i = 0; i < argc; i++) { - args[i] = env.get(mem[argv >> 2]); - argv += 4; - } - - try { - let res = fn.apply(thisArg, args); - return env.createValue(res, result); - } catch (err) { - env.pendingException = err; - return NAPI_PENDING_EXCEPTION; - } - }, - napi_new_instance(env_id, cons, argc, argv, result) { - let env = environments[env_id]; - let Class = env.get(cons); - let args = new Array(argc); - let mem = env.u32; - for (let i = 0; i < argc; i++) { - args[i] = env.get(mem[argv >> 2]); - argv += 4; - } - - try { - let value = new Class(...args); - return env.createValue(value, result); - } catch (err) { - env.pendingException = err; - return NAPI_PENDING_EXCEPTION; - } - }, - napi_get_cb_info(env_id, cbinfo, argc, argv, thisArg, data) { - let env = environments[env_id]; - let info = env.get(cbinfo); - env.setPointer(argc, info.args.length); - for (let i = 0; i < info.args.length; i++) { - env.createValue(info.args[i], argv); - argv += 4; - } - env.createValue(info.thisArg, thisArg); - env.setPointer(data, info.data); - return NAPI_OK; - }, - napi_get_new_target(env_id, cbinfo, result) { - let env = environments[env_id]; - let info = env.get(cbinfo); - return env.createValue(info.newTarget, result); - }, - napi_create_threadsafe_function( - env_id, - func, - async_resource, - async_resource_name, - max_queue_size, - initial_thread_count, - thread_finalize_data, - thread_finalize_cb, - context, - call_js_cb, - result - ) { - let env = environments[env_id]; - let fn = func ? env.get(func) : undefined; - let cb = call_js_cb ? env.table.get(call_js_cb) : undefined; - let f = new ThreadSafeFunction(env, fn, cb, context); - - if (thread_finalize_cb) { - let cb = env.table.get(thread_finalize_cb); - finalizationRegistry.register(f, new FinalizeRecord(env_id, cb, 0, f.id)); - } - - env.setPointer(result, f.id); - return NAPI_OK; - }, - napi_ref_threadsafe_function() { - return NAPI_OK; - }, - napi_unref_threadsafe_function() { - return NAPI_OK; - }, - napi_acquire_threadsafe_function() { - return NAPI_OK; - }, - napi_release_threadsafe_function(func, mode) { - threadsafeFunctions[func] = undefined; - return NAPI_OK; - }, - napi_call_threadsafe_function(func, data, is_blocking) { - let f = threadsafeFunctions[func]; - f.env.pushScope(); - try { - if (f.nativeFn) { - let id = f.fn ? f.env.pushValue(f.fn) : 0; - f.nativeFn(f.env.id, id, f.context, data); - } else if (f.fn) { - f.fn(); - } - } finally { - f.env.popScope(); - } - }, - napi_get_threadsafe_function_context(func, result) { - let f = threadsafeFunctions[func]; - f.env.setPointer(result, f.context); - return NAPI_OK; - }, - napi_create_async_work(env_id, async_resource, async_resource_name, execute, complete, data, result) { - let env = environments[env_id]; - let executeFn = execute ? env.table.get(execute) : undefined; - let completeFn = complete ? env.table.get(complete) : undefined; - let w = new AsyncWork(env, executeFn, completeFn, data); - env.setPointer(result, w.id); - return NAPI_OK; - }, - napi_delete_async_work(env, work) { - asyncWork[work] = undefined; - return NAPI_OK; - }, - napi_queue_async_work(env, work) { - queueMicrotask(() => { - let w = asyncWork[work]; - if (w) { - w.execute(env, w.data); - w.complete(env, NAPI_OK, w.data); - } - }); - return NAPI_OK; - }, - napi_cancel_async_work() { - let w = asyncWork[work]; - w.complete(env, NAPI_CANCELED, w.data); - asyncWork[work] = undefined; - return NAPI_OK; - }, - napi_throw(env_id, error) { - let env = environments[env_id]; - env.pendingException = env.get(error); - return NAPI_OK; - }, - napi_throw_error(env_id, code, msg) { - let env = environments[env_id]; - let err = new Error(env.getString(msg)); - err.code = code; - env.pendingException = err; - return NAPI_OK; - }, - napi_throw_type_error(env_id, code, msg) { - let env = environments[env_id]; - let err = new TypeError(env.getString(msg)); - err.code = code; - env.pendingException = err; - return NAPI_OK; - }, - napi_throw_range_error(env_id, code, msg) { - let env = environments[env_id]; - let err = new RangeError(env.getString(msg)); - err.code = code; - env.pendingException = err; - return NAPI_OK; - }, - napi_create_error(env_id, code, msg, result) { - let env = environments[env_id]; - let err = new Error(env.get(msg)); - err.code = env.get(code); - return env.createValue(err, result); - }, - napi_create_type_error(env_id, code, msg, result) { - let env = environments[env_id]; - let err = new TypeError(env.get(msg)); - err.code = env.get(code); - return env.createValue(err, result); - }, - napi_create_range_error(env_id, code, msg, result) { - let env = environments[env_id]; - let err = new RangeError(env.get(msg)); - err.code = env.get(code); - return env.createValue(err, result); - }, - napi_get_and_clear_last_exception(env_id, result) { - let env = environments[env_id]; - let e = env.pendingException; - env.pendingException = null; - return env.createValue(e, result); - }, - napi_is_exception_pending(env_id, result) { - let env = environments[env_id]; - env.memory[result] = env.pendingException ? 1 : 0; - return NAPI_OK; - }, - napi_fatal_exception(env_id, err) { - throw new Error('not implemented'); - }, - napi_fatal_error(location, location_len, message, message_len) { - throw new Error('not implemented'); - }, - napi_get_global(env_id, result) { - let env = environments[env_id]; - return env.setPointer(result, 2); - }, - napi_create_buffer(env_id, length, data, result) { - let env = environments[env_id]; - let ptr = env.instance.exports.napi_wasm_malloc(length); - if (data) { - env.setPointer(data, ptr); - } - - // Return a view into WASM memory. - let buf = typeof globalThis.Buffer !== 'undefined' - ? globalThis.Buffer.from(env.memory.buffer, ptr, length) - : env.memory.subarray(ptr, ptr + length); - return env.createValue(buf, result); - }, - napi_create_buffer_copy(env_id, length, data, result_data, result) { - let env = environments[env_id]; - let ptr = env.instance.exports.napi_wasm_malloc(length); - env.memory.set(env.memory.subarray(data, data + length), ptr); - if (result_data) { - env.setPointer(result_data, ptr); - } - - // Return a view into WASM memory. - let res = typeof globalThis.Buffer !== 'undefined' - ? globalThis.Buffer.from(env.memory.buffer, ptr, length) - : env.memory.subarray(ptr, ptr + length); - return env.createValue(res, result); - }, - napi_create_external_buffer(env_id, length, data, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let buf = typeof globalThis.Buffer !== 'undefined' - ? globalThis.Buffer.from(env.memory.buffer, data, length) - : env.memory.subarray(data, data + length); - if (finalize_cb) { - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(buf, new FinalizeRecord(env_id, cb, finalize_hint, data)); - } - - return env.createValue(buf, result); - }, - napi_get_buffer_info(env_id, value, data, length) { - let env = environments[env_id]; - let buf = env.get(value); - let len = env.getBufferInfo(buf, data); - return env.setPointer(length, len); - }, - napi_create_arraybuffer(env_id, length, data, result) { - let env = environments[env_id]; - let buf = new ArrayBuffer(length); - if (data) { - // This copies the ArrayBuffer into the WASM memory. - env.getBufferInfo(buf, data); - } - return env.createValue(buf, result); - }, - napi_create_external_arraybuffer(env_id, data, length, finalize_cb, finalize_hint, result) { - // There is no way to actually create an external ArrayBuffer without copying. - // You can only create typed arrays as subarrays, not ArrayBuffer. - return NAPI_NO_EXTERNAL_BUFFERS_ALLOWED; - }, - napi_get_arraybuffer_info(env_id, value, data, length) { - let env = environments[env_id]; - let len = env.getBufferInfo(env.get(value), data); - return env.setPointer(length, len); - }, - napi_detach_arraybuffer(env_id, arraybuffer) { - let env = environments[env_id]; - let buffer = env.get(arraybuffer); - if (typeof structuredClone === 'function') { - structuredClone(buffer, {transfer: [buffer]}); - } - return NAPI_OK; - }, - napi_is_detached_arraybuffer(env_id, arraybuffer, result) { - let env = environments[env_id]; - let buffer = env.get(arraybuffer); - env.memory[result] = buffer.byteLength === 0 ? 1 : 0; // ?? - return NAPI_OK; - }, - napi_create_typedarray(env_id, type, length, arraybuffer, offset, result) { - let env = environments[env_id]; - let Class = typedArrays[type]; - let buffer = env.get(arraybuffer); - let buf = new Class(buffer, offset, length); - return env.createValue(buf, result); - }, - napi_create_dataview(env_id, byte_length, arraybuffer, byte_offset, result) { - let env = environments[env_id]; - let buffer = env.get(arraybuffer); - let view = new DataView(buffer, byte_offset, byte_length); - return env.createValue(view, result); - }, - napi_get_typedarray_info(env_id, typedarray, type, length, data, arraybuffer, byte_offset) { - let env = environments[env_id]; - let val = env.get(typedarray); - env.setPointer(type, typedArrays.indexOf(val.constructor)); - env.setPointer(length, val.length); - env.getBufferInfo(val, data); - env.createValue(val.buffer, arraybuffer); - return env.setPointer(byte_offset, val.byteOffset); - }, - napi_get_dataview_info(env_id, dataview, byte_length, data, arraybuffer, byte_offset) { - let env = environments[env_id]; - let val = env.get(dataview); - env.setPointer(byte_length, val.byteLength); - env.getBufferInfo(val, data); - env.createValue(val.buffer, arraybuffer); - return env.setPointer(byte_offset, val.byteOffset); - }, - napi_create_string_utf8(env_id, str, length, result) { - let env = environments[env_id]; - let s = decoder.decode(env.memory.subarray(str, str + length)); - return env.createValue(s, result); - }, - napi_get_value_string_utf8(env_id, value, buf, bufsize, result) { - let env = environments[env_id]; - let val = env.get(value); - if (buf == 0) { - return env.setPointer(result, utf8Length(val)); - } - let res = encoder.encodeInto(val, env.memory.subarray(buf, buf + bufsize - 1)); - env.memory[buf + res.written] = 0; // null terminate - return env.setPointer(result, res.written); - }, - napi_create_string_latin1(env_id, str, length, result) { - let env = environments[env_id]; - let s = latin1Decoder.decode(env.memory.subarray(str, str + length)); - return env.createValue(s, result); - }, - napi_get_value_string_latin1(env_id, value, buf, bufsize, result) { - let env = environments[env_id]; - let val = env.get(value); - if (buf == 0) { - return env.setPointer(result, val.length); - } - let mem = env.memory; - let len = Math.min(val.length, bufsize - 1); - for (let i = 0; i < len; i++) { - let code = val.charCodeAt(i); - mem[buf++] = code; - } - mem[buf] = 0; // null terminate - return env.setPointer(result, len); - }, - napi_create_string_utf16(env_id, str, length, result) { - let env = environments[env_id]; - let s = utf16Decoder.decode(env.memory.subarray(str, str + length * 2)); - return env.createValue(s, result); - }, - napi_get_value_string_utf16(env_id, value, buf, bufsize, result) { - let env = environments[env_id]; - let val = env.get(value); - if (buf == 0) { - return env.setPointer(result, val.length); - } - let mem = env.u16; - let ptr = buf >> 1; - let len = Math.min(val.length, bufsize - 1); - for (let i = 0; i < len; i++) { - let code = val.charCodeAt(i); - mem[ptr++] = code; - } - mem[ptr] = 0; // null terminate - return env.setPointer(result, len); - }, - napi_create_date(env_id, time, result) { - let env = environments[env_id]; - return env.createValue(new Date(time), result); - }, - napi_get_date_value(env_id, value, result) { - let env = environments[env_id]; - let date = env.get(value); - env.f64[result >> 3] = date.valueOf(); - }, - napi_create_symbol(env_id, description, result) { - let env = environments[env_id]; - let desc = env.get(description); - return env.createValue(Symbol(desc), result); - }, - napi_coerce_to_bool(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Boolean(env.get(value)), result); - }, - napi_coerce_to_number(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Number(env.get(value)), result); - }, - napi_coerce_to_object(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Object(env.get(value)), result); - }, - napi_coerce_to_string(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(String(env.get(value)), result); - }, - napi_typeof(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - return env.setPointer(result, (() => { - switch (typeof val) { - case 'undefined': - return 0; - case 'boolean': - return 2; - case 'number': - return 3; - case 'string': - return 4; - case 'symbol': - return 5; - case 'object': - if (val === null) { - return 1; - } else if (val instanceof ExternalValue) { - return 8; - } - return 6; - case 'function': - return 7; - case 'bigint': - return 9; - } - })()); - }, - napi_instanceof(env_id, object, constructor, result) { - let env = environments[env_id]; - let obj = env.get(object); - let cons = env.get(constructor); - env.memory[result] = obj instanceof cons ? 1 : 0; - return NAPI_OK; - }, - napi_is_array(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = Array.isArray(val) ? 1 : 0; - return NAPI_OK; - }, - napi_is_buffer(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = (typeof globalThis.Buffer !== 'undefined' ? globalThis.Buffer.isBuffer(val) : val instanceof Uint8Array) ? 1 : 0; - return NAPI_OK; - }, - napi_is_date(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val instanceof Date ? 1 : 0; - return NAPI_OK; - }, - napi_is_error(env_id, value, result) { - let env = environments[env_id]; - let err = env.get(value); - env.memory[result] = err instanceof Error ? 1 : 0; - return NAPI_OK; - }, - napi_is_typedarray(env_id, value, result) { - let env = environments[env_id]; - let buf = env.get(value); - env.memory[result] = ArrayBuffer.isView(buf) && !(buf instanceof DataView) ? 1 : 0; - return NAPI_OK; - }, - napi_is_dataview(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val instanceof DataView ? 1 : 0; - return NAPI_OK; - }, - napi_strict_equals(env_id, lhs, rhs, result) { - let env = environments[env_id]; - env.memory[result] = env.get(lhs) === env.get(rhs) ? 1 : 0; - return NAPI_OK; - }, - napi_wrap(env_id, js_object, native_object, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - env.wrappedObjects.set(obj, native_object); - if (finalize_cb) { - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(obj, new FinalizeRecord(env_id, cb, finalize_hint, native_object)); - } - - if (result) { - return napi.napi_create_reference(env_id, js_object, 1, result); - } - - return NAPI_OK; - }, - napi_unwrap(env_id, js_object, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - let native_object = env.wrappedObjects.get(obj); - env.setPointer(result, native_object); - return NAPI_OK; - }, - napi_remove_wrap(env_id, js_object, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - let native_object = env.wrappedObjects.get(obj); - finalizationRegistry.unregister(obj); - env.wrappedObjects.delete(obj); - return env.setPointer(result, native_object); - }, - napi_type_tag_object(env_id, js_object, type_tag) { - throw new Error('not implemented'); - }, - napi_check_object_type_tag(env_id, js_object, type_tag) { - throw new Error('not implemented'); - }, - napi_add_finalizer(env_id, js_object, native_object, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(obj, new FinalizeRecord(env_id, cb, finalize_hint, native_object)); - if (result) { - return napi.napi_create_reference(env_id, js_object, 1, result); - } - - return NAPI_OK; - }, - napi_create_promise(env_id, deferred, promise) { - let env = environments[env_id]; - let p = new Promise((resolve, reject) => { - let id = env.deferred.length; - env.deferred.push({resolve, reject}); - env.setPointer(deferred, id); - }); - return env.createValue(p, promise); - }, - napi_resolve_deferred(env_id, deferred, resolution) { - let env = environments[env_id]; - let { resolve } = env.deferred[deferred]; - let value = env.get(resolution); - resolve(value); - env.deferred[deferred] = undefined; - return NAPI_OK; - }, - napi_reject_deferred(env_id, deferred, rejection) { - let env = environments[env_id]; - let { reject } = env.deferred[deferred]; - let value = env.get(rejection); - reject(value); - env.deferred[deferred] = undefined; - return NAPI_OK; - }, - napi_is_promise(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val instanceof Promise ? 1 : 0; - return NAPI_OK; - }, - napi_run_script(env_id, script, result) { - let env = environments[env_id]; - let source = env.get(script); - let res = (0, eval)(source); - return env.createValue(res, result); - }, - napi_create_external(env_id, data, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let external = new ExternalValue; - env.externalObjects.set(external, data); - if (finalize_cb) { - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(external, new FinalizeRecord(env_id, cb, finalize_hint, data)); - } - return env.createValue(external, result); - }, - napi_get_value_external(env_id, value, result) { - let env = environments[env_id]; - let external = env.get(value); - let val = env.externalObjects.get(external); - return env.setPointer(result, val); - }, - napi_adjust_external_memory() { - return NAPI_OK; - } -}; - -function strlen(buf, ptr) { - let len = 0; - while (buf[ptr] !== 0) { - len++; - ptr++; - } - - return len; -} - -function utf8Length(string) { - let len = 0; - for (let i = 0; i < string.length; i++) { - let c = string.charCodeAt(i); - - if (c >= 0xd800 && c <= 0xdbff && i < string.length - 1) { - let c2 = string.charCodeAt(++i); - if ((c2 & 0xfc00) === 0xdc00) { - c = ((c & 0x3ff) << 10) + (c2 & 0x3ff) + 0x10000; - } else { - // unmatched surrogate. - i--; - } - } - - if ((c & 0xffffff80) === 0) { - len++; - } else if ((c & 0xfffff800) === 0) { - len += 2; - } else if ((c & 0xffff0000) === 0) { - len += 3; - } else if ((c & 0xffe00000) === 0) { - len += 4; - } - } - return len; -} - -exports.Environment = Environment; -exports.napi = napi; diff --git a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/index.mjs b/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/index.mjs deleted file mode 100644 index 1955eb9..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/index.mjs +++ /dev/null @@ -1,1371 +0,0 @@ -const NAPI_OK = 0; -const NAPI_GENERIC_FAILURE = 9; -const NAPI_PENDING_EXCEPTION = 10; -const NAPI_CANCELED = 11; -const NAPI_HANDLE_SCOPE_MISMATCH = 13; -const NAPI_NO_EXTERNAL_BUFFERS_ALLOWED = 22; - -// https://nodejs.org/api/n-api.html#napi_property_attributes -const NAPI_WRITABLE = 1 << 0; -const NAPI_ENUMERABLE = 1 << 1; -const NAPI_CONFIGURABLE = 1 << 2; -const NAPI_STATIC = 1 << 10; - -// https://nodejs.org/api/n-api.html#napi_typedarray_type -const typedArrays = [ - Int8Array, - Uint8Array, - Uint8ClampedArray, - Int16Array, - Uint16Array, - Int32Array, - Uint32Array, - Float32Array, - Float64Array, - BigInt64Array, - BigUint64Array -]; - -const environments = []; - -export class Environment { - scopes = []; - referenceId = 1; - references = new Map(); - deferred = [null]; - wrappedObjects = new WeakMap(); - externalObjects = new WeakMap(); - buffers = new Map(); - instanceData = 0; - pendingException = null; - - constructor(instance) { - this.id = environments.length; - environments.push(this); - - this.instance = instance; - this.table = instance.exports.__indirect_function_table; - this.exports = {}; - - this.pushScope(); - let values = this.scopes[this.scopes.length - 1]; - let exports = values.length; - values.push(this.exports); - - try { - if (this.instance.exports.napi_register_module_v1) { - this.instance.exports.napi_register_module_v1(this.id, exports); - } - - if (this.instance.exports.napi_register_wasm_v1) { - this.instance.exports.napi_register_wasm_v1(this.id, exports); - } - } finally { - this.popScope(); - if (this.pendingException) { - let e = this.pendingException; - this.pendingException = null; - throw e; - } - } - } - - destroy() { - environments[this.id] = undefined; - } - - getString(ptr, len = strlen(this.memory, ptr)) { - return decoder.decode(this.memory.subarray(ptr, Math.max(0, ptr + len))); - } - - pushScope() { - let id = this.scopes.length; - this.scopes.push(id ? [...this.scopes[id - 1]] : [undefined, null, globalThis, true, false]); - return id; - } - - popScope() { - this.scopes.pop(); - - // Update any buffers with values which might have been modified in WASM copy. - for (let [buffer, slice] of this.buffers) { - // Ignore if buffer or slice has been detached. - if (buffer.byteLength && slice.byteLength) { - buffer.set(slice); - } - } - - this.buffers.clear(); - } - - get(idx) { - return this.scopes[this.scopes.length - 1][idx]; - } - - set(idx, value) { - this.scopes[this.scopes.length - 1][idx] = value; - } - - pushValue(value, scope = this.scopes.length - 1) { - let values = this.scopes[scope]; - let id = values.length; - values.push(value); - return id; - } - - createValue(value, result, scope) { - if (typeof value === 'boolean') { - this.setPointer(result, value ? 3 : 4); - return NAPI_OK; - } else if (typeof value === 'undefined') { - this.setPointer(result, 0); - return NAPI_OK; - } else if (value === null) { - this.setPointer(result, 1); - return NAPI_OK; - } else if (value === globalThis) { - this.setPointer(result, 2); - return NAPI_OK; - } - - let id = this.pushValue(value, scope); - this.setPointer(result, id); - return NAPI_OK; - } - - setPointer(ptr, value) { - this.u32[ptr >> 2] = value; - return NAPI_OK; - } - - _u32 = new Uint32Array(); - get u32() { - if (this._u32.byteLength === 0) { - this._u32 = new Uint32Array(this.instance.exports.memory.buffer); - } - - return this._u32; - } - - _i32 = new Int32Array(); - get i32() { - if (this._i32.byteLength === 0) { - this._i32 = new Int32Array(this.instance.exports.memory.buffer); - } - - return this._i32; - } - - _u16 = new Uint16Array(); - get u16() { - if (this._u16.byteLength === 0) { - this._u16 = new Uint16Array(this.instance.exports.memory.buffer); - } - - return this._u16; - } - - _u64 = new BigUint64Array(); - get u64() { - if (this._u64.byteLength === 0) { - this._u64 = new BigUint64Array(this.instance.exports.memory.buffer); - } - - return this._u64; - } - - _i64 = new BigInt64Array(); - get i64() { - if (this._i64.byteLength === 0) { - this._i64 = new BigInt64Array(this.instance.exports.memory.buffer); - } - - return this._i64; - } - - _f64 = new Float64Array(); - get f64() { - if (this._f64.byteLength === 0) { - this._f64 = new Float64Array(this.instance.exports.memory.buffer); - } - - return this._f64; - } - - _buf = new Uint8Array(); - get memory() { - if (this._buf.byteLength === 0) { - this._buf = new Uint8Array(this.instance.exports.memory.buffer); - } - - return this._buf; - } - - getBufferInfo(buf, ptr) { - if (this.buffers.has(buf)) { - let b = this.buffers.get(buf); - this.setPointer(ptr, b.byteOffset); - return b.byteLength; - } - - if (buf instanceof ArrayBuffer) { - let b = this.copyBuffer(new Uint8Array(buf)); - this.setPointer(ptr, b.byteOffset); - return b.byteLength; - } - - // If this is a view into WASM memory, no copies needed. - if (buf.buffer === this.instance.exports.memory.buffer) { - this.setPointer(ptr, buf.byteOffset); - return buf.byteLength; - } - - let b = this.copyBuffer(new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength)); - this.setPointer(ptr, b.byteOffset); - return b.byteLength; - } - - copyBuffer(data) { - let ptr = this.instance.exports.napi_wasm_malloc(data.byteLength); - let mem = this.memory; - mem.set(data, ptr); - let buf = mem.subarray(ptr, ptr + data.byteLength); - this.buffers.set(data, buf); - return buf; - } - - createFunction(cb, data) { - let env = this; - let fn = env.table.get(cb); - let func = function (...args) { - let scope = env.pushScope(); - - try { - let values = env.scopes[scope]; - let info = values.length; - values.push({ - thisArg: this, - args, - data, - newTarget: new.target - }); - - let res = fn(env.id, info); - return env.get(res); - } finally { - env.popScope(); - if (env.pendingException) { - let e = env.pendingException; - env.pendingException = null; - throw e; - } - } - }; - - return func; - } - - readPropertyDescriptor(ptr) { - // https://nodejs.org/api/n-api.html#napi_property_descriptor - let buf = this.u32; - let utf8name = buf[ptr++]; - let nameValue = buf[ptr++]; - let method = buf[ptr++]; - let getter = buf[ptr++]; - let setter = buf[ptr++]; - let val = buf[ptr++]; - let attrs = buf[ptr++]; - let data = buf[ptr++]; - - let name = utf8name ? this.getString(utf8name) : this.get(nameValue); - let writable = Boolean(attrs & NAPI_WRITABLE); - let enumerable = Boolean(attrs & NAPI_ENUMERABLE); - let configurable = Boolean(attrs & NAPI_CONFIGURABLE); - let isStatic = Boolean(attrs & NAPI_STATIC); - let get = getter ? this.createFunction(getter, data) : undefined; - let set = setter ? this.createFunction(setter, data) : undefined; - let value = method ? this.createFunction(method, data) : val ? this.get(val) : undefined; - - let descriptor = { - name, - static: isStatic, - configurable, - enumerable - }; - if (get || set) { - descriptor.get = get; - descriptor.set = set; - } else if (value) { - descriptor.writable = writable; - descriptor.value = value; - } - - return descriptor; - } -} - -const decoder = new TextDecoder("utf-8", { ignoreBOM: true, fatal: true }); -const latin1Decoder = new TextDecoder('latin1'); -const utf16Decoder = new TextDecoder('utf-16'); -const encoder = new TextEncoder(); - -class FinalizeRecord { - constructor(env, finalize, hint, data) { - this.env = env; - this.finalize = finalize; - this.hint = hint; - this.data = data; - } -} - -const finalizationRegistry = new FinalizationRegistry(buffer => { - if (buffer.finalize) { - buffer.finalize(buffer.env, buffer.data, buffer.hint); - } -}); - -class ExternalValue {} - -const threadsafeFunctions = []; - -class ThreadSafeFunction { - constructor(env, fn, nativeFn, context) { - this.env = env; - this.fn = fn; - this.nativeFn = nativeFn; - this.context = context; - this.id = threadsafeFunctions.length; - threadsafeFunctions.push(this); - } -} - -const asyncWork = [null]; - -class AsyncWork { - constructor(env, execute, complete, data) { - this.env = env; - this.execute = execute; - this.complete = complete; - this.data = data; - this.id = asyncWork.length; - asyncWork.push(this); - } -} - -export const napi = { - napi_open_handle_scope(env_id, result) { - let env = environments[env_id]; - let id = env.pushScope(); - return env.setPointer(result, id); - }, - napi_close_handle_scope(env_id, scope) { - let env = environments[env_id]; - if (scope !== env.scopes.length - 1) { - return NAPI_HANDLE_SCOPE_MISMATCH; - } - env.popScope(); - return NAPI_OK; - }, - napi_open_escapable_handle_scope(env_id, result) { - let env = environments[env_id]; - let id = env.pushScope(); - return env.setPointer(result, id); - }, - napi_close_escapable_handle_scope(env_id, scope) { - let env = environments[env_id]; - if (scope !== env.scopes.length - 1) { - return NAPI_HANDLE_SCOPE_MISMATCH; - } - env.popScope(); - return NAPI_OK; - }, - napi_escape_handle(env_id, scope_id, escapee, result) { - let env = environments[env_id]; - let value = env.get(escapee); - // Create a value in the outer scope. - return env.createValue(value, result, scope_id - 1); - }, - napi_create_object(env_id, result) { - let env = environments[env_id]; - return env.createValue({}, result); - }, - napi_set_property(env_id, object, key, value) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - let val = env.get(value); - obj[name] = val; - return NAPI_OK; - }, - napi_get_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - return env.createValue(obj[name], result); - }, - napi_delete_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - let res = false; - try { - res = delete obj[name]; - } catch (err) {} - if (result) { - env.memory[result] = res ? 1 : 0; - } - return NAPI_OK; - }, - napi_has_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - // return env.setPointer(result, name in obj ? 1 : 0); - env.memory[result] = name in obj ? 1 : 0; - return NAPI_OK; - }, - napi_has_own_property(env_id, object, key, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.get(key); - env.memory[result] = obj.hasOwnProperty(name) ? 1 : 0; - return NAPI_OK; - }, - napi_set_named_property(env_id, object, utf8Name, value) { - let env = environments[env_id]; - let obj = env.get(object); - let val = env.get(value); - let name = env.getString(utf8Name); - obj[name] = val; - return NAPI_OK; - }, - napi_get_named_property(env_id, object, utf8Name, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.getString(utf8Name); - return env.createValue(obj[name], result); - }, - napi_has_named_property(env_id, object, utf8Name, result) { - let env = environments[env_id]; - let obj = env.get(object); - let name = env.getString(utf8Name); - env.memory[result] = name in obj ? 1 : 0; - return NAPI_OK; - }, - napi_get_property_names(env_id, object, result) { - let env = environments[env_id]; - let obj = env.get(object); - let properties = Object.keys(obj); - return env.createValue(properties, result); - }, - napi_get_all_property_names(env_id, object, key_mode, key_filter, key_conversion, result) { - throw new Error('not implemented'); - }, - napi_define_properties(env_id, object, property_count, properties) { - let env = environments[env_id]; - let obj = env.get(object); - let ptr = properties >> 2; - for (let i = 0; i < property_count; i++) { - let descriptor = env.readPropertyDescriptor(ptr); - Object.defineProperty(obj, descriptor.name, descriptor); - ptr += 8; - } - return NAPI_OK; - }, - napi_object_freeze(env_id, object) { - let env = environments[env_id]; - let obj = env.get(object); - Object.freeze(obj); - return NAPI_OK; - }, - napi_object_seal(env_id, object) { - let env = environments[env_id]; - let obj = env.get(object); - Object.seal(obj); - return NAPI_OK; - }, - napi_get_prototype(env_id, object, result) { - let env = environments[env_id]; - let obj = env.get(object); - return env.createValue(Object.getPrototypeOf(obj), result); - }, - napi_define_class(env_id, utf8name, length, constructor, data, property_count, properties, result) { - let env = environments[env_id]; - let func = env.createFunction(constructor, data); - - Object.defineProperty(func, 'name', { - value: env.getString(utf8name, length), - configurable: true - }); - - let ptr = properties >> 2; - for (let i = 0; i < property_count; i++) { - let descriptor = env.readPropertyDescriptor(ptr); - if (descriptor.static) { - Object.defineProperty(func, descriptor.name, descriptor); - } else { - Object.defineProperty(func.prototype, descriptor.name, descriptor); - } - ptr += 8; - } - - return env.createValue(func, result); - }, - napi_create_reference(env_id, value, refcount, result) { - let env = environments[env_id]; - let id = env.referenceId++; - env.references.set(id, { - value: env.get(value), - refcount - }); - return env.setPointer(result, id); - }, - napi_delete_reference(env_id, ref) { - let env = environments[env_id]; - env.references.delete(ref); - return NAPI_OK; - }, - napi_get_reference_value(env_id, ref, result) { - let env = environments[env_id]; - let reference = env.references.get(ref); - return env.createValue(reference.value, result); - }, - napi_reference_ref(env_id, ref, result) { - let env = environments[env_id]; - let reference = env.references.get(ref); - reference.refcount++; - return env.setPointer(result, reference.refcount); - }, - napi_reference_unref(env_id, ref, result) { - let env = environments[env_id]; - let reference = env.references.get(ref); - if (reference.refcount === 0) { - return NAPI_GENERIC_FAILURE; - } - reference.refcount--; - return env.setPointer(result, reference.refcount); - }, - napi_add_env_cleanup_hook() { - return NAPI_OK; - }, - napi_remove_env_cleanup_hook() { - return NAPI_OK; - }, - napi_add_async_cleanup_hook() { - return NAPI_OK; - }, - napi_remove_async_cleanup_hook() { - return NAPI_OK; - }, - napi_set_instance_data(env_id, data, finalize_cb, finalize_hint) { - let env = environments[env_id]; - env.instanceData = data; - return NAPI_OK; - }, - napi_get_instance_data(env_id, data) { - let env = environments[env_id]; - return env.setPointer(data, env.instanceData); - }, - napi_get_boolean(env_id, value, result) { - let env = environments[env_id]; - return env.setPointer(result, value ? 3 : 4); - }, - napi_get_value_bool(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val ? 1 : 0; - return NAPI_OK; - }, - napi_create_int32(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(value, result); - }, - napi_get_value_int32(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.i32[result >> 2] = val; - return NAPI_OK; - }, - napi_create_uint32(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(value, result); - }, - napi_get_value_uint32(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - return env.setPointer(result, val); - }, - napi_create_int64(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Number(value), result); - }, - napi_get_value_int64(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.i64[result >> 3] = val; - return NAPI_OK; - }, - napi_create_double(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(value, result); - }, - napi_get_value_double(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.f64[result >> 3] = val; - return NAPI_OK; - }, - napi_create_bigint_int64(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(BigInt.asIntN(64, value), result); - }, - napi_get_value_bigint_int64(env_id, value, result, lossless) { - let env = environments[env_id]; - let val = env.get(value); - env.i64[result >> 3] = val; - if (lossless) { - env.memory[lossless] = BigInt.asIntN(64, val) === val ? 1 : 0; - } - return NAPI_OK; - }, - napi_create_bigint_uint64(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(BigInt.asUintN(64, value), result); - }, - napi_get_value_bigint_uint64(env_id, value, result, lossless) { - let env = environments[env_id]; - let val = env.get(value); - env.u64[result >> 3] = val; - if (lossless) { - env.memory[lossless] = BigInt.asUintN(64, val) === val ? 1 : 0; - } - return NAPI_OK; - }, - napi_create_bigint_words(env_id, sign_bit, word_count, words, result) { - let env = environments[env_id]; - let buf = env.u64; - let ptr = words >> 3; - let res = 0n; - let shift = 0n; - - for (let i = 0; i < word_count; i++) { - let word = buf[ptr++]; - res += word << shift; - shift += 64n; - } - - res *= BigInt((-1) ** sign_bit); - return env.createValue(res, result); - }, - napi_get_value_bigint_words(env_id, value, sign_bit, word_count, words) { - let env = environments[env_id]; - let val = env.get(value); - let count = env.u32[word_count >> 2]; - - if (sign_bit) { - env.i32[sign_bit] = val < 0n ? 1 : 0; - } - - let i = 0; - if (words) { - let mask = (1n << 64n) - 1n; - let buf = env.u64; - let ptr = words >> 3; - if (val < 0n) { - val = -val; - } - - for (; i < count && val !== 0n; i++) { - buf[ptr++] = val & mask; - val >>= 64n; - } - } - - while (val > 0n) { - i++; - val >>= 64n; - } - - return env.setPointer(word_count, i); - }, - napi_get_null(env_id, result) { - let env = environments[env_id]; - return env.setPointer(result, 1); - }, - napi_create_array(env_id, result) { - let env = environments[env_id]; - return env.createValue([], result); - }, - napi_create_array_with_length(env_id, length, result) { - let env = environments[env_id]; - return env.createValue(new Array(length), result); - }, - napi_set_element(env_id, object, index, value) { - let env = environments[env_id]; - let obj = env.get(object); - let val = env.get(value); - obj[index] = val; - return NAPI_OK; - }, - napi_get_element(env_id, object, index, result) { - let env = environments[env_id]; - let obj = env.get(object); - let val = obj[index]; - return env.createValue(val, result); - }, - napi_has_element(env_id, object, index, result) { - let env = environments[env_id]; - let obj = env.get(object); - env.memory[result] = obj.hasOwnProperty(index) ? 1 : 0; - return NAPI_OK; - }, - napi_delete_element(env_id, object, index, result) { - let env = environments[env_id]; - let obj = env.get(object); - let res = false; - try { - res = delete obj[index]; - } catch (err) {} - if (result) { - env.memory[result] = res ? 1 : 0; - } - return NAPI_OK; - }, - napi_get_array_length(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - return env.setPointer(result, val.length); - }, - napi_get_undefined(env_id, result) { - let env = environments[env_id]; - return env.setPointer(result, 0); - }, - napi_create_function(env_id, utf8name, length, cb, data, result) { - let env = environments[env_id]; - let func = env.createFunction(cb, data); - - Object.defineProperty(func, 'name', { - value: env.getString(utf8name, length), - configurable: true - }); - - return env.createValue(func, result); - }, - napi_call_function(env_id, recv, func, argc, argv, result) { - let env = environments[env_id]; - let thisArg = env.get(recv); - let fn = env.get(func); - let args = new Array(argc); - let mem = env.u32; - for (let i = 0; i < argc; i++) { - args[i] = env.get(mem[argv >> 2]); - argv += 4; - } - - try { - let res = fn.apply(thisArg, args); - return env.createValue(res, result); - } catch (err) { - env.pendingException = err; - return NAPI_PENDING_EXCEPTION; - } - }, - napi_new_instance(env_id, cons, argc, argv, result) { - let env = environments[env_id]; - let Class = env.get(cons); - let args = new Array(argc); - let mem = env.u32; - for (let i = 0; i < argc; i++) { - args[i] = env.get(mem[argv >> 2]); - argv += 4; - } - - try { - let value = new Class(...args); - return env.createValue(value, result); - } catch (err) { - env.pendingException = err; - return NAPI_PENDING_EXCEPTION; - } - }, - napi_get_cb_info(env_id, cbinfo, argc, argv, thisArg, data) { - let env = environments[env_id]; - let info = env.get(cbinfo); - env.setPointer(argc, info.args.length); - for (let i = 0; i < info.args.length; i++) { - env.createValue(info.args[i], argv); - argv += 4; - } - env.createValue(info.thisArg, thisArg); - env.setPointer(data, info.data); - return NAPI_OK; - }, - napi_get_new_target(env_id, cbinfo, result) { - let env = environments[env_id]; - let info = env.get(cbinfo); - return env.createValue(info.newTarget, result); - }, - napi_create_threadsafe_function( - env_id, - func, - async_resource, - async_resource_name, - max_queue_size, - initial_thread_count, - thread_finalize_data, - thread_finalize_cb, - context, - call_js_cb, - result - ) { - let env = environments[env_id]; - let fn = func ? env.get(func) : undefined; - let cb = call_js_cb ? env.table.get(call_js_cb) : undefined; - let f = new ThreadSafeFunction(env, fn, cb, context); - - if (thread_finalize_cb) { - let cb = env.table.get(thread_finalize_cb); - finalizationRegistry.register(f, new FinalizeRecord(env_id, cb, 0, f.id)); - } - - env.setPointer(result, f.id); - return NAPI_OK; - }, - napi_ref_threadsafe_function() { - return NAPI_OK; - }, - napi_unref_threadsafe_function() { - return NAPI_OK; - }, - napi_acquire_threadsafe_function() { - return NAPI_OK; - }, - napi_release_threadsafe_function(func, mode) { - threadsafeFunctions[func] = undefined; - return NAPI_OK; - }, - napi_call_threadsafe_function(func, data, is_blocking) { - let f = threadsafeFunctions[func]; - f.env.pushScope(); - try { - if (f.nativeFn) { - let id = f.fn ? f.env.pushValue(f.fn) : 0; - f.nativeFn(f.env.id, id, f.context, data); - } else if (f.fn) { - f.fn(); - } - } finally { - f.env.popScope(); - } - }, - napi_get_threadsafe_function_context(func, result) { - let f = threadsafeFunctions[func]; - f.env.setPointer(result, f.context); - return NAPI_OK; - }, - napi_create_async_work(env_id, async_resource, async_resource_name, execute, complete, data, result) { - let env = environments[env_id]; - let executeFn = execute ? env.table.get(execute) : undefined; - let completeFn = complete ? env.table.get(complete) : undefined; - let w = new AsyncWork(env, executeFn, completeFn, data); - env.setPointer(result, w.id); - return NAPI_OK; - }, - napi_delete_async_work(env, work) { - asyncWork[work] = undefined; - return NAPI_OK; - }, - napi_queue_async_work(env, work) { - queueMicrotask(() => { - let w = asyncWork[work]; - if (w) { - w.execute(env, w.data); - w.complete(env, NAPI_OK, w.data); - } - }); - return NAPI_OK; - }, - napi_cancel_async_work() { - let w = asyncWork[work]; - w.complete(env, NAPI_CANCELED, w.data); - asyncWork[work] = undefined; - return NAPI_OK; - }, - napi_throw(env_id, error) { - let env = environments[env_id]; - env.pendingException = env.get(error); - return NAPI_OK; - }, - napi_throw_error(env_id, code, msg) { - let env = environments[env_id]; - let err = new Error(env.getString(msg)); - err.code = code; - env.pendingException = err; - return NAPI_OK; - }, - napi_throw_type_error(env_id, code, msg) { - let env = environments[env_id]; - let err = new TypeError(env.getString(msg)); - err.code = code; - env.pendingException = err; - return NAPI_OK; - }, - napi_throw_range_error(env_id, code, msg) { - let env = environments[env_id]; - let err = new RangeError(env.getString(msg)); - err.code = code; - env.pendingException = err; - return NAPI_OK; - }, - napi_create_error(env_id, code, msg, result) { - let env = environments[env_id]; - let err = new Error(env.get(msg)); - err.code = env.get(code); - return env.createValue(err, result); - }, - napi_create_type_error(env_id, code, msg, result) { - let env = environments[env_id]; - let err = new TypeError(env.get(msg)); - err.code = env.get(code); - return env.createValue(err, result); - }, - napi_create_range_error(env_id, code, msg, result) { - let env = environments[env_id]; - let err = new RangeError(env.get(msg)); - err.code = env.get(code); - return env.createValue(err, result); - }, - napi_get_and_clear_last_exception(env_id, result) { - let env = environments[env_id]; - let e = env.pendingException; - env.pendingException = null; - return env.createValue(e, result); - }, - napi_is_exception_pending(env_id, result) { - let env = environments[env_id]; - env.memory[result] = env.pendingException ? 1 : 0; - return NAPI_OK; - }, - napi_fatal_exception(env_id, err) { - throw new Error('not implemented'); - }, - napi_fatal_error(location, location_len, message, message_len) { - throw new Error('not implemented'); - }, - napi_get_global(env_id, result) { - let env = environments[env_id]; - return env.setPointer(result, 2); - }, - napi_create_buffer(env_id, length, data, result) { - let env = environments[env_id]; - let ptr = env.instance.exports.napi_wasm_malloc(length); - if (data) { - env.setPointer(data, ptr); - } - - // Return a view into WASM memory. - let buf = typeof globalThis.Buffer !== 'undefined' - ? globalThis.Buffer.from(env.memory.buffer, ptr, length) - : env.memory.subarray(ptr, ptr + length); - return env.createValue(buf, result); - }, - napi_create_buffer_copy(env_id, length, data, result_data, result) { - let env = environments[env_id]; - let ptr = env.instance.exports.napi_wasm_malloc(length); - env.memory.set(env.memory.subarray(data, data + length), ptr); - if (result_data) { - env.setPointer(result_data, ptr); - } - - // Return a view into WASM memory. - let res = typeof globalThis.Buffer !== 'undefined' - ? globalThis.Buffer.from(env.memory.buffer, ptr, length) - : env.memory.subarray(ptr, ptr + length); - return env.createValue(res, result); - }, - napi_create_external_buffer(env_id, length, data, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let buf = typeof globalThis.Buffer !== 'undefined' - ? globalThis.Buffer.from(env.memory.buffer, data, length) - : env.memory.subarray(data, data + length); - if (finalize_cb) { - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(buf, new FinalizeRecord(env_id, cb, finalize_hint, data)); - } - - return env.createValue(buf, result); - }, - napi_get_buffer_info(env_id, value, data, length) { - let env = environments[env_id]; - let buf = env.get(value); - let len = env.getBufferInfo(buf, data); - return env.setPointer(length, len); - }, - napi_create_arraybuffer(env_id, length, data, result) { - let env = environments[env_id]; - let buf = new ArrayBuffer(length); - if (data) { - // This copies the ArrayBuffer into the WASM memory. - env.getBufferInfo(buf, data); - } - return env.createValue(buf, result); - }, - napi_create_external_arraybuffer(env_id, data, length, finalize_cb, finalize_hint, result) { - // There is no way to actually create an external ArrayBuffer without copying. - // You can only create typed arrays as subarrays, not ArrayBuffer. - return NAPI_NO_EXTERNAL_BUFFERS_ALLOWED; - }, - napi_get_arraybuffer_info(env_id, value, data, length) { - let env = environments[env_id]; - let len = env.getBufferInfo(env.get(value), data); - return env.setPointer(length, len); - }, - napi_detach_arraybuffer(env_id, arraybuffer) { - let env = environments[env_id]; - let buffer = env.get(arraybuffer); - if (typeof structuredClone === 'function') { - structuredClone(buffer, {transfer: [buffer]}); - } - return NAPI_OK; - }, - napi_is_detached_arraybuffer(env_id, arraybuffer, result) { - let env = environments[env_id]; - let buffer = env.get(arraybuffer); - env.memory[result] = buffer.byteLength === 0 ? 1 : 0; // ?? - return NAPI_OK; - }, - napi_create_typedarray(env_id, type, length, arraybuffer, offset, result) { - let env = environments[env_id]; - let Class = typedArrays[type]; - let buffer = env.get(arraybuffer); - let buf = new Class(buffer, offset, length); - return env.createValue(buf, result); - }, - napi_create_dataview(env_id, byte_length, arraybuffer, byte_offset, result) { - let env = environments[env_id]; - let buffer = env.get(arraybuffer); - let view = new DataView(buffer, byte_offset, byte_length); - return env.createValue(view, result); - }, - napi_get_typedarray_info(env_id, typedarray, type, length, data, arraybuffer, byte_offset) { - let env = environments[env_id]; - let val = env.get(typedarray); - env.setPointer(type, typedArrays.indexOf(val.constructor)); - env.setPointer(length, val.length); - env.getBufferInfo(val, data); - env.createValue(val.buffer, arraybuffer); - return env.setPointer(byte_offset, val.byteOffset); - }, - napi_get_dataview_info(env_id, dataview, byte_length, data, arraybuffer, byte_offset) { - let env = environments[env_id]; - let val = env.get(dataview); - env.setPointer(byte_length, val.byteLength); - env.getBufferInfo(val, data); - env.createValue(val.buffer, arraybuffer); - return env.setPointer(byte_offset, val.byteOffset); - }, - napi_create_string_utf8(env_id, str, length, result) { - let env = environments[env_id]; - let s = decoder.decode(env.memory.subarray(str, str + length)); - return env.createValue(s, result); - }, - napi_get_value_string_utf8(env_id, value, buf, bufsize, result) { - let env = environments[env_id]; - let val = env.get(value); - if (buf == 0) { - return env.setPointer(result, utf8Length(val)); - } - let res = encoder.encodeInto(val, env.memory.subarray(buf, buf + bufsize - 1)); - env.memory[buf + res.written] = 0; // null terminate - return env.setPointer(result, res.written); - }, - napi_create_string_latin1(env_id, str, length, result) { - let env = environments[env_id]; - let s = latin1Decoder.decode(env.memory.subarray(str, str + length)); - return env.createValue(s, result); - }, - napi_get_value_string_latin1(env_id, value, buf, bufsize, result) { - let env = environments[env_id]; - let val = env.get(value); - if (buf == 0) { - return env.setPointer(result, val.length); - } - let mem = env.memory; - let len = Math.min(val.length, bufsize - 1); - for (let i = 0; i < len; i++) { - let code = val.charCodeAt(i); - mem[buf++] = code; - } - mem[buf] = 0; // null terminate - return env.setPointer(result, len); - }, - napi_create_string_utf16(env_id, str, length, result) { - let env = environments[env_id]; - let s = utf16Decoder.decode(env.memory.subarray(str, str + length * 2)); - return env.createValue(s, result); - }, - napi_get_value_string_utf16(env_id, value, buf, bufsize, result) { - let env = environments[env_id]; - let val = env.get(value); - if (buf == 0) { - return env.setPointer(result, val.length); - } - let mem = env.u16; - let ptr = buf >> 1; - let len = Math.min(val.length, bufsize - 1); - for (let i = 0; i < len; i++) { - let code = val.charCodeAt(i); - mem[ptr++] = code; - } - mem[ptr] = 0; // null terminate - return env.setPointer(result, len); - }, - napi_create_date(env_id, time, result) { - let env = environments[env_id]; - return env.createValue(new Date(time), result); - }, - napi_get_date_value(env_id, value, result) { - let env = environments[env_id]; - let date = env.get(value); - env.f64[result >> 3] = date.valueOf(); - }, - napi_create_symbol(env_id, description, result) { - let env = environments[env_id]; - let desc = env.get(description); - return env.createValue(Symbol(desc), result); - }, - napi_coerce_to_bool(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Boolean(env.get(value)), result); - }, - napi_coerce_to_number(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Number(env.get(value)), result); - }, - napi_coerce_to_object(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(Object(env.get(value)), result); - }, - napi_coerce_to_string(env_id, value, result) { - let env = environments[env_id]; - return env.createValue(String(env.get(value)), result); - }, - napi_typeof(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - return env.setPointer(result, (() => { - switch (typeof val) { - case 'undefined': - return 0; - case 'boolean': - return 2; - case 'number': - return 3; - case 'string': - return 4; - case 'symbol': - return 5; - case 'object': - if (val === null) { - return 1; - } else if (val instanceof ExternalValue) { - return 8; - } - return 6; - case 'function': - return 7; - case 'bigint': - return 9; - } - })()); - }, - napi_instanceof(env_id, object, constructor, result) { - let env = environments[env_id]; - let obj = env.get(object); - let cons = env.get(constructor); - env.memory[result] = obj instanceof cons ? 1 : 0; - return NAPI_OK; - }, - napi_is_array(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = Array.isArray(val) ? 1 : 0; - return NAPI_OK; - }, - napi_is_buffer(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = (typeof globalThis.Buffer !== 'undefined' ? globalThis.Buffer.isBuffer(val) : val instanceof Uint8Array) ? 1 : 0; - return NAPI_OK; - }, - napi_is_date(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val instanceof Date ? 1 : 0; - return NAPI_OK; - }, - napi_is_error(env_id, value, result) { - let env = environments[env_id]; - let err = env.get(value); - env.memory[result] = err instanceof Error ? 1 : 0; - return NAPI_OK; - }, - napi_is_typedarray(env_id, value, result) { - let env = environments[env_id]; - let buf = env.get(value); - env.memory[result] = ArrayBuffer.isView(buf) && !(buf instanceof DataView) ? 1 : 0; - return NAPI_OK; - }, - napi_is_dataview(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val instanceof DataView ? 1 : 0; - return NAPI_OK; - }, - napi_strict_equals(env_id, lhs, rhs, result) { - let env = environments[env_id]; - env.memory[result] = env.get(lhs) === env.get(rhs) ? 1 : 0; - return NAPI_OK; - }, - napi_wrap(env_id, js_object, native_object, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - env.wrappedObjects.set(obj, native_object); - if (finalize_cb) { - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(obj, new FinalizeRecord(env_id, cb, finalize_hint, native_object)); - } - - if (result) { - return napi.napi_create_reference(env_id, js_object, 1, result); - } - - return NAPI_OK; - }, - napi_unwrap(env_id, js_object, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - let native_object = env.wrappedObjects.get(obj); - env.setPointer(result, native_object); - return NAPI_OK; - }, - napi_remove_wrap(env_id, js_object, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - let native_object = env.wrappedObjects.get(obj); - finalizationRegistry.unregister(obj); - env.wrappedObjects.delete(obj); - return env.setPointer(result, native_object); - }, - napi_type_tag_object(env_id, js_object, type_tag) { - throw new Error('not implemented'); - }, - napi_check_object_type_tag(env_id, js_object, type_tag) { - throw new Error('not implemented'); - }, - napi_add_finalizer(env_id, js_object, native_object, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let obj = env.get(js_object); - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(obj, new FinalizeRecord(env_id, cb, finalize_hint, native_object)); - if (result) { - return napi.napi_create_reference(env_id, js_object, 1, result); - } - - return NAPI_OK; - }, - napi_create_promise(env_id, deferred, promise) { - let env = environments[env_id]; - let p = new Promise((resolve, reject) => { - let id = env.deferred.length; - env.deferred.push({resolve, reject}); - env.setPointer(deferred, id); - }); - return env.createValue(p, promise); - }, - napi_resolve_deferred(env_id, deferred, resolution) { - let env = environments[env_id]; - let { resolve } = env.deferred[deferred]; - let value = env.get(resolution); - resolve(value); - env.deferred[deferred] = undefined; - return NAPI_OK; - }, - napi_reject_deferred(env_id, deferred, rejection) { - let env = environments[env_id]; - let { reject } = env.deferred[deferred]; - let value = env.get(rejection); - reject(value); - env.deferred[deferred] = undefined; - return NAPI_OK; - }, - napi_is_promise(env_id, value, result) { - let env = environments[env_id]; - let val = env.get(value); - env.memory[result] = val instanceof Promise ? 1 : 0; - return NAPI_OK; - }, - napi_run_script(env_id, script, result) { - let env = environments[env_id]; - let source = env.get(script); - let res = (0, eval)(source); - return env.createValue(res, result); - }, - napi_create_external(env_id, data, finalize_cb, finalize_hint, result) { - let env = environments[env_id]; - let external = new ExternalValue; - env.externalObjects.set(external, data); - if (finalize_cb) { - let cb = env.table.get(finalize_cb); - finalizationRegistry.register(external, new FinalizeRecord(env_id, cb, finalize_hint, data)); - } - return env.createValue(external, result); - }, - napi_get_value_external(env_id, value, result) { - let env = environments[env_id]; - let external = env.get(value); - let val = env.externalObjects.get(external); - return env.setPointer(result, val); - }, - napi_adjust_external_memory() { - return NAPI_OK; - } -}; - -function strlen(buf, ptr) { - let len = 0; - while (buf[ptr] !== 0) { - len++; - ptr++; - } - - return len; -} - -function utf8Length(string) { - let len = 0; - for (let i = 0; i < string.length; i++) { - let c = string.charCodeAt(i); - - if (c >= 0xd800 && c <= 0xdbff && i < string.length - 1) { - let c2 = string.charCodeAt(++i); - if ((c2 & 0xfc00) === 0xdc00) { - c = ((c & 0x3ff) << 10) + (c2 & 0x3ff) + 0x10000; - } else { - // unmatched surrogate. - i--; - } - } - - if ((c & 0xffffff80) === 0) { - len++; - } else if ((c & 0xfffff800) === 0) { - len += 2; - } else if ((c & 0xffff0000) === 0) { - len += 3; - } else if ((c & 0xffe00000) === 0) { - len += 4; - } - } - return len; -} diff --git a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/package.json b/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/package.json deleted file mode 100644 index ce6ee25..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/node_modules/napi-wasm/package.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "napi-wasm", - "version": "1.1.0", - "description": "An implementation of napi for wasm", - "main": "index.mjs", - "exports": { - "import": "./index.mjs", - "require": "./index.js" - }, - "files": [ - "index.js", - "index.mjs" - ], - "scripts": { - "prepublishOnly": "sed 's/^export //g' index.mjs > index.js && echo '\nexports.Environment = Environment;\nexports.napi = napi;' >> index.js" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/devongovett/napi-wasm.git" - }, - "keywords": [ - "napi", - "wasm", - "node-api", - "rust" - ], - "author": "Devon Govett ", - "license": "MIT", - "bugs": { - "url": "https://github.com/devongovett/napi-wasm/issues" - }, - "homepage": "https://github.com/devongovett/napi-wasm#readme" -} diff --git a/dapp/node_modules/@parcel/watcher-wasm/package.json b/dapp/node_modules/@parcel/watcher-wasm/package.json deleted file mode 100644 index f4ae117..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/package.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "@parcel/watcher-wasm", - "version": "2.3.0", - "main": "index.mjs", - "types": "index.d.ts", - "repository": { - "type": "git", - "url": "https://github.com/parcel-bundler/watcher.git" - }, - "description": "A native C++ Node module for querying and subscribing to filesystem events. Used by Parcel 2.", - "license": "MIT", - "publishConfig": { - "access": "public" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "files": [ - "*.js", - "*.mjs", - "*.d.ts", - "*.wasm" - ], - "engines": { - "node": ">= 10.0.0" - }, - "dependencies": { - "napi-wasm": "^1.1.0", - "is-glob": "^4.0.3", - "micromatch": "^4.0.5" - }, - "module": "index.mjs", - "sideEffects": false, - "bundledDependencies": [ - "napi-wasm" - ] -} diff --git a/dapp/node_modules/@parcel/watcher-wasm/watcher.wasm b/dapp/node_modules/@parcel/watcher-wasm/watcher.wasm deleted file mode 100644 index 0623b495e3b94d81941fa133b0608758f14ae7a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 110770 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 F<{tn*k469h diff --git a/dapp/node_modules/@parcel/watcher-wasm/wrapper.js b/dapp/node_modules/@parcel/watcher-wasm/wrapper.js deleted file mode 100644 index 496d56b..0000000 --- a/dapp/node_modules/@parcel/watcher-wasm/wrapper.js +++ /dev/null @@ -1,77 +0,0 @@ -const path = require('path'); -const micromatch = require('micromatch'); -const isGlob = require('is-glob'); - -function normalizeOptions(dir, opts = {}) { - const { ignore, ...rest } = opts; - - if (Array.isArray(ignore)) { - opts = { ...rest }; - - for (const value of ignore) { - if (isGlob(value)) { - if (!opts.ignoreGlobs) { - opts.ignoreGlobs = []; - } - - const regex = micromatch.makeRe(value, { - // We set `dot: true` to workaround an issue with the - // regular expression on Linux where the resulting - // negative lookahead `(?!(\\/|^)` was never matching - // in some cases. See also https://bit.ly/3UZlQDm - dot: true, - // C++ does not support lookbehind regex patterns, they - // were only added later to JavaScript engines - // (https://bit.ly/3V7S6UL) - lookbehinds: false - }); - opts.ignoreGlobs.push(regex.source); - } else { - if (!opts.ignorePaths) { - opts.ignorePaths = []; - } - - opts.ignorePaths.push(path.resolve(dir, value)); - } - } - } - - return opts; -} - -exports.createWrapper = (binding) => { - return { - writeSnapshot(dir, snapshot, opts) { - return binding.writeSnapshot( - path.resolve(dir), - path.resolve(snapshot), - normalizeOptions(dir, opts), - ); - }, - getEventsSince(dir, snapshot, opts) { - return binding.getEventsSince( - path.resolve(dir), - path.resolve(snapshot), - normalizeOptions(dir, opts), - ); - }, - async subscribe(dir, fn, opts) { - dir = path.resolve(dir); - opts = normalizeOptions(dir, opts); - await binding.subscribe(dir, fn, opts); - - return { - unsubscribe() { - return binding.unsubscribe(dir, fn, opts); - }, - }; - }, - unsubscribe(dir, fn, opts) { - return binding.unsubscribe( - path.resolve(dir), - fn, - normalizeOptions(dir, opts), - ); - } - }; -}; diff --git a/src/tests/bwc_staking_contract/nmmn b/src/tests/bwc_staking_contract/nmmn deleted file mode 100644 index e69de29..0000000