diff --git a/README.md b/README.md
index 96b4fcd2..6b6c0e24 100644
--- a/README.md
+++ b/README.md
@@ -7,10 +7,11 @@
The Starknet snap allows developers to **deploy Starknet accounts, make transactions on Starknet, and interact with Starknet smart contracts.** It can be connected with any dapp to access Starknet and developers can experiment integrating their dapp with this snap today.
-[Starknet dapp](https://snaps.consensys.net/starknet)
+[Starknet Snap](https://snaps.metamask.io/snap/npm/consensys/starknet-snap)
-[Blog post](https://consensys.net/blog/metamask/metamask-integrates-starkware-into-first-of-its-kind-zk-rollup-snap/)
+[Starknet Dapp](https://snaps.consensys.io/starknet)
+[Blog Post](https://consensys.io/blog/metamask/metamask-integrates-starkware-into-first-of-its-kind-zk-rollup-snap/)
# Development
### Prerequisites
@@ -61,6 +62,40 @@ yarn workspace wallet-ui storybook
- Wallet UI dapp: http://localhost:3000/
- Storybook: http://localhost:6006/
+# Dapp intergation Guide
+
+### How to install
+From the dApp, issue the following RPC request to install the Snap, make sure it is using the latest version
+```javascript
+provider.request({
+ method: 'wallet_requestSnaps',
+ params: {
+ ["npm:@consensys/starknet-snap"]: { version: "2.2.0"}, //Snap's version
+ },
+})
+```
+
+### Interact with Starknet Snap's Api
+From the dApp, issue the following RPC request to interact with the Snap
+
+e.g
+```javascript
+provider.request({
+ method: 'wallet_invokeSnap',
+ params: {
+ snapId: "npm:@consensys/starknet-snap",
+ request: {
+ method: 'starkNet_getStoredUserAccounts', //Snap method
+ params: {
+ chainId : "1", //Snap method's parameter
+ },
+ },
+ },
+}))
+```
+### Starknet Snap's Api
+The corresponding request payload and response for latest Starknet Snap's Api are documented in the [openrpc spec](https://github.com/Consensys/starknet-snap/blob/starknet-snap-v2.2.0/packages/starknet-snap/openrpc/starknet_snap_api_openrpc.json)
+
# Licenses
This project is dual-licensed under Apache 2.0 and MIT terms:
@@ -68,4 +103,4 @@ This project is dual-licensed under Apache 2.0 and MIT terms:
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
-Copyright (c) 2022 ConsenSys Software Inc.
+Copyright (c) 2023 ConsenSys Software Inc.
diff --git a/packages/starknet-snap/.eslintrc.js b/packages/starknet-snap/.eslintrc.js
index 7ddfcaa4..0a8f4696 100644
--- a/packages/starknet-snap/.eslintrc.js
+++ b/packages/starknet-snap/.eslintrc.js
@@ -3,17 +3,13 @@ module.exports = {
browser: true,
es2021: true,
},
- extends: [
- 'plugin:@typescript-eslint/recommended',
- ],
+ extends: ['plugin:@typescript-eslint/recommended'],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
- plugins: [
- '@typescript-eslint',
- ],
+ plugins: ['@typescript-eslint'],
rules: {
},
};
diff --git a/packages/starknet-snap/index.html b/packages/starknet-snap/index.html
index 3cad5b40..2913a5a9 100644
--- a/packages/starknet-snap/index.html
+++ b/packages/starknet-snap/index.html
@@ -1,992 +1,905 @@
-
+
Hello, Snaps!
-
-
-
- Hello, Snaps!
-
- Instructions
-
- - First, click "Connect". Then, try out the other buttons!
- - Please note that:
+
+
+
+ Hello, Snaps!
+
+ Instructions
- -
- The
snap.manifest.json
and package.json
must be located in the server root
- directory..
-
- -
- The Snap bundle must be hosted at the location specified by the
location
field of
- snap.manifest.json
.
-
+ - First, click "Connect". Then, try out the other buttons!
+ - Please note that:
+
+ -
+ The
snap.manifest.json
and package.json
must be located in the server root
+ directory..
+
+ -
+ The Snap bundle must be hosted at the location specified by the
location
field of
+ snap.manifest.json
.
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ // here we call the snap's "starkNet_estimateFee" method
+ async function getEstimateFee(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const contractAddress = document.getElementById('contractAddress').value;
+ const contractFuncName = document.getElementById('contractFuncName').value;
+ const contractCallData = document.getElementById('contractCallData').value;
+ const senderAddress = document.getElementById('feeSenderAddress').value;
+
+ await callSnap('starkNet_estimateFee', { contractAddress, contractFuncName, contractCallData, senderAddress });
+ }
+
+ // here we call the snap's "starkNet_estimateAccountDeployFee" method
+ async function getEstimateAccountDeployFee(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const addressIndex = document.getElementById('estimateDeployFeeAddressIndex').value;
+
+ await callSnap('starkNet_estimateAccountDeployFee', { addressIndex });
+ }
-
\ No newline at end of file
+ // here we call the snap's "starkNet_sendTransaction" method
+ async function transferErc20(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const erc20Address = document.getElementById('transferTokenAddress').value;
+ const recipientAddress = document.getElementById('recipientAddress').value;
+ const transferAmount = document.getElementById('transferAmount').value;
+ const senderAddress = document.getElementById('senderAddress').value;
+ const maxFee = document.getElementById('transferMaxFee').value;
+
+ await callSnap('starkNet_sendTransaction', {
+ erc20Address,
+ recipientAddress,
+ transferAmount,
+ senderAddress,
+ maxFee,
+ });
+ }
+
+ // here we call the snap's "starkNet_getStoredUserAccounts" method
+ async function getDeployedAccContracts(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ await callSnap('starkNet_getStoredUserAccounts', {});
+ }
+
+ // here we call the snap's "starkNet_getTransactionStatus" method
+ async function getTransactionStatus(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const transactionHash = document.getElementById('transactionHash').value;
+
+ await callSnap('starkNet_getTransactionStatus', { transactionHash });
+ }
+
+ // here we call the snap's "starkNet_createAccount" method
+ async function deployUserAccContract(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const addressIndex = document.getElementById('addressIndex').value;
+ const deploy = document.getElementById('sendDeployTxn').checked;
+
+ await callSnap('starkNet_createAccount', { addressIndex, deploy });
+ }
+
+ // here we call the snap's "starkNet_extractPrivateKey" method
+ async function retrievePrivateKeyFromAddress(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const userAddress = document.getElementById('userAddress').value;
+
+ await callSnap('starkNet_extractPrivateKey', { userAddress });
+ }
+
+ // here we call the snap's "starkNet_extractPublicKey" method
+ async function retrievePublicKeyFromAddress(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const userAddress = document.getElementById('pkUserAddress').value;
+
+ await callSnap('starkNet_extractPublicKey', { userAddress });
+ }
+
+ // here we call the snap's "starkNet_signMessage" method
+ async function signTypedDataMessage(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const typedDataMessage = document.getElementById('typedDataMessage').value;
+ const signerAddress = document.getElementById('signerUserAddress').value;
+
+ await callSnap('starkNet_signMessage', {
+ typedDataMessage: typedDataMessage ? JSON.parse(typedDataMessage) : {},
+ signerAddress,
+ });
+ }
+
+ // here we call the snap's "starkNet_signTransaction" method
+ async function signTransaction(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const userAddress = document.getElementById('signTransaction_userAddress').value;
+ const transactions = document.getElementById('signTransaction_transactions').value;
+ const transactionsDetail = document.getElementById('signTransaction_transactionsDetail').value;
+
+ await callSnap('starkNet_signTransaction', {
+ signerAddress: userAddress,
+ transactions: transactions ? JSON.parse(transactions) : {},
+ transactionsDetail: transactionsDetail ? JSON.parse(transactionsDetail) : {},
+ });
+ }
+
+ // here we call the snap's "starkNet_signDeployAccounrTransaction" method
+ async function signDeployAccountTransaction(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const userAddress = document.getElementById('signDeployAccountTransaction_userAddress').value;
+ const transaction = document.getElementById('signDeployAccountTransaction_transaction').value;
+
+ await callSnap('starkNet_signDeployAccounrTransaction', {
+ signerAddress: userAddress,
+ transaction: transaction ? JSON.parse(transaction) : {},
+ });
+ }
+
+ // here we call the snap's "starkNet_signDeclareTransaction" method
+ async function signDeclareTransaction(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const userAddress = document.getElementById('signDeclareTransaction_userAddress').value;
+ const transaction = document.getElementById('signDeclareTransaction_transaction').value;
+
+ await callSnap('starkNet_signDeclareTransaction', {
+ signerAddress: userAddress,
+ transaction: transaction ? JSON.parse(transaction) : {},
+ });
+ }
+
+ // here we call the snap's "starkNet_verifySignedMessage" method
+ async function verifyTypedDataSignature(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const typedDataMessage = document.getElementById('verifyTypedDataMessage').value;
+ const signerAddress = document.getElementById('verifySignerUserAddress').value;
+ const signature = document.getElementById('verifySignature').value;
+
+ await callSnap('starkNet_verifySignedMessage', { typedDataMessage, signerAddress, signature });
+ }
+
+ // here we call the snap's "starkNet_addErc20Token" method
+ async function addErc20Token(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const tokenAddress = document.getElementById('addTokenAddress').value;
+ const tokenName = document.getElementById('addTokenName').value;
+ const tokenSymbol = document.getElementById('addTokenSymbol').value;
+ const tokenDecimals = document.getElementById('addTokenDecimals').value;
+
+ await callSnap('starkNet_addErc20Token', { tokenAddress, tokenName, tokenSymbol, tokenDecimals });
+ }
+
+ // here we call the snap's "starkNet_getStoredErc20Tokens" method
+ async function getStoredErc20Tokens(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ await callSnap('starkNet_getStoredErc20Tokens', {});
+ }
+
+ // here we call the snap's "starkNet_sendTransaction" method
+ async function sendTransaction(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const contractAddress = document.getElementById('txnContractAddress').value;
+ const contractFuncName = document.getElementById('txnContractFuncName').value;
+ const contractCallData = document.getElementById('txnContractCallData').value;
+ const senderAddress = document.getElementById('txnSenderAddress').value;
+ const maxFee = document.getElementById('txnMaxFee').value;
+ const chainId = document.getElementById('targetChainId').value;
+
+ await callSnap('starkNet_sendTransaction', {
+ contractAddress,
+ contractFuncName,
+ contractCallData,
+ senderAddress,
+ maxFee,
+ });
+ }
+
+ // here we call the snap's "starkNet_getValue" method
+ async function callContract(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const contractAddress = document.getElementById('callContractAddress').value;
+ const contractFuncName = document.getElementById('callContractFuncName').value;
+ const contractCallData = document.getElementById('callContractCallData').value;
+ const chainId = document.getElementById('targetChainId').value;
+
+ await callSnap('starkNet_getValue', { contractAddress, contractFuncName, contractCallData });
+ }
+
+ // here we call the snap's "starkNet_addNetwork" method
+ async function addNetwork(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const networkName = document.getElementById('addNetworkName').value;
+ const networkChainId = document.getElementById('addNetworkChainId').value;
+ const networkBaseUrl = document.getElementById('addNetworkBaseUrl').value;
+ const networkNodeUrl = document.getElementById('addNetworkNodeUrl').value;
+ const networkVoyagerUrl = document.getElementById('addNetworkVoyagerUrl').value;
+ const accountClassHash = document.getElementById('addNetworkAccClassHash').value;
+
+ await callSnap('starkNet_addNetwork', {
+ networkName,
+ networkChainId,
+ networkBaseUrl,
+ networkNodeUrl,
+ networkVoyagerUrl,
+ accountClassHash,
+ });
+ }
+
+ // here we call the snap's "starkNet_switchNetwork" method
+ async function switchNetwork(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const networkChainId = document.getElementById('switchNetwork_ChainId').value;
+
+ await callSnap('starkNet_switchNetwork', {
+ chainId: networkChainId,
+ });
+ }
+
+ // here we call the snap's "starkNet_getCurrentNetwork" method
+ async function getCurrentNetwork(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ await callSnap('starkNet_getCurrentNetwork', {});
+ }
+
+ // here we call the snap's "starkNet_getStoredNetworks" method
+ async function getStoredNetworks(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ await callSnap('starkNet_getStoredNetworks', {});
+ }
+
+ // here we call the snap's "starkNet_getStoredTransactions" method
+ async function getStoredTransactions(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const senderAddress = document.getElementById('getTxnSenderAddress').value;
+ const contractAddress = document.getElementById('getTxnContractAddress').value;
+ const txnType = document.getElementById('txnType').value;
+ const txnsInLastNumOfDays = document.getElementById('txnInLastNumOfDays').value;
+
+ await callSnap('starkNet_getStoredTransactions', {
+ senderAddress,
+ contractAddress,
+ txnType,
+ txnsInLastNumOfDays,
+ });
+ }
+
+ // here we call the snap's "starkNet_getTransactions" method
+ async function getTransactions(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const senderAddress = document.getElementById('getTxnsSenderAddress').value;
+ const contractAddress = document.getElementById('getTxnsContractAddress').value;
+ const pageSize = document.getElementById('getTxnsPageSize').value;
+ const txnsInLastNumOfDays = document.getElementById('getTxnsInLastNumOfDays').value;
+ const onlyFromState = document.getElementById('getTxnsOnlyFromState').checked;
+ const withDeployTxn = document.getElementById('getTxnsWithDeployTxn').checked;
+
+ await callSnap('starkNet_getTransactions', {
+ senderAddress,
+ contractAddress,
+ pageSize,
+ txnsInLastNumOfDays,
+ onlyFromState,
+ withDeployTxn,
+ });
+ }
+
+ // here we call the snap's "starkNet_recoverAccounts" method
+ async function recoverUserAccounts(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const startScanIndex = document.getElementById('startScanIndex').value;
+ const maxScanned = document.getElementById('maxScanned').value;
+ const maxMissed = document.getElementById('maxMissed').value;
+
+ await callSnap('starkNet_recoverAccounts', {
+ startScanIndex,
+ maxScanned,
+ maxMissed,
+ });
+ }
+
+ async function executeTxn(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const senderAddress = document.getElementById('executetxn_senderAddress').value;
+ const txnInvocation = document.getElementById('executetxn_txnInvocation').value;
+ const abis = document.getElementById('executetxn_abis').value;
+ const invocationsDetails = document.getElementById('executetxn_invocationsDetails').value;
+
+ await callSnap('starkNet_executeTxn', {
+ senderAddress,
+ txnInvocation: txnInvocation ? JSON.parse(txnInvocation) : undefined,
+ abis: abis ? JSON.parse(abis) : undefined,
+ invocationsDetails: invocationsDetails ? JSON.parse(invocationsDetails) : undefined,
+ });
+ }
+
+ async function declareContract(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const senderAddress = document.getElementById('declareContract_senderAddress').value;
+ const contractPayload = document.getElementById('declareContract_contract').value;
+ const invocationsDetails = document.getElementById('declareContract_invocationsDetails').value;
+
+ await callSnap('starkNet_declareContract', {
+ senderAddress,
+ contractPayload: contractPayload ? JSON.parse(contractPayload) : contractPayload,
+ invocationsDetails: invocationsDetails ? JSON.parse(invocationsDetails) : invocationsDetails,
+ });
+ }
+
+ async function estimateFees(e) {
+ e.preventDefault(); // to prevent default form behavior
+
+ const senderAddress = document.getElementById('estimateFees_senderAddress').value;
+ const invocationDetails = document.getElementById('estimateFees_invocationDetails').value;
+ const invocations = document.getElementById('estimateFees_invocations').value;
+
+ await callSnap('starkNet_estimateFees', {
+ senderAddress,
+ invocations: invocations ? JSON.parse(invocations) : undefined,
+ invocationDetails: invocationDetails ? JSON.parse(invocationDetails) : undefined,
+ });
+ }
+
+ async function callSnap(method, params) {
+ try {
+ const chainId = document.getElementById('targetChainId').value;
+ //0x534e5f474f45524c42
+ console.log(params)
+ const response = await ethereum.request({
+ method: 'wallet_invokeSnap',
+ params: {
+ snapId,
+ request: {
+ method: method,
+ params: {
+ chainId,
+ ...getReqFlagsFromCheckbox(),
+ ...params,
+ },
+ },
+ },
+ });
+ console.log(`${method} response:`, response);
+ } catch (err) {
+ console.error(`${method} problem happened:`, err);
+ alert(`${method} problem happened: ${err.message || err}`);
+ }
+ }
+
+
diff --git a/packages/starknet-snap/openrpc/starknet_snap_api_openrpc.json b/packages/starknet-snap/openrpc/starknet_snap_api_openrpc.json
index a6c18645..510f7b4b 100644
--- a/packages/starknet-snap/openrpc/starknet_snap_api_openrpc.json
+++ b/packages/starknet-snap/openrpc/starknet_snap_api_openrpc.json
@@ -846,6 +846,327 @@
}
},
"errors": []
+ },
+ {
+ "name": "starkNet_estimateFees",
+ "summary": "Get multiple estimated gas fee",
+ "paramStructure": "by-name",
+ "params": [
+ {
+ "name": "senderAddress",
+ "summary": "Address of the account contract",
+ "description": "Address of the account contract",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/ADDRESS"
+ }
+ },
+ {
+ "name": "chainId",
+ "summary": "Id of the target Starknet network",
+ "description": "Id of the target Starknet network (default to Starknet Goerli Testnet)",
+ "required": false,
+ "schema": {
+ "$ref": "#/components/schemas/CHAIN_ID"
+ }
+ },
+ {
+ "name": "invocations",
+ "summary": "Transaction(s)",
+ "description": "Array with consist of transaction payload and transaction type",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/INVOCATIONS"
+ }
+ },
+ {
+ "name": "invocationDetails",
+ "summary": "Transaction configurate parameters",
+ "description": "A struct consist of maxFee, nonce and version",
+ "required": false,
+ "schema": {
+ "$ref": "#/components/schemas/INVOCATION_DETAILS"
+ }
+ }
+ ],
+ "result": {
+ "name": "result",
+ "summary": "List of gas fee estimate object",
+ "description": "List of gas fee estimate object",
+ "schema": {
+ "$ref": "#/components/schemas/ESTIMATE_FEE_RESULTS"
+ }
+ },
+ "errors": []
+ },
+ {
+ "name": "starkNet_executeTxn",
+ "summary": "Execute multiple txn",
+ "paramStructure": "by-name",
+ "params": [
+ {
+ "name": "senderAddress",
+ "summary": "Address of the account contract",
+ "description": "Address of the account contract",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/ADDRESS"
+ }
+ },
+ {
+ "name": "chainId",
+ "summary": "Id of the target Starknet network",
+ "description": "Id of the target Starknet network (default to Starknet Goerli Testnet)",
+ "required": false,
+ "schema": {
+ "$ref": "#/components/schemas/CHAIN_ID"
+ }
+ },
+ {
+ "name": "txnInvocation",
+ "summary": "Transaction(s)",
+ "description": "Array or Object that consist of transaction payload",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/INVOCATION_PAYLOAD"
+ }
+ },
+ {
+ "name": "abis",
+ "summary": "abis",
+ "description": "Array or Object that consist of abi",
+ "required": false,
+ "schema": {
+ "$ref": "#/components/schemas/ABIS"
+ }
+ },
+ {
+ "name": "invocationDetails",
+ "summary": "Transaction configurate parameters",
+ "description": "A struct consist of maxFee, nonce and version",
+ "required": false,
+ "schema": {
+ "$ref": "#/components/schemas/INVOCATION_DETAILS"
+ }
+ }
+ ],
+ "result": {
+ "name": "result",
+ "summary": "Transaction result",
+ "description": "Transaction result consist of transaction hash",
+ "schema": {
+ "$ref": "#/components/schemas/SEND_TRANSACTION_RESULT"
+ }
+ },
+ "errors": []
+ },
+ {
+ "name": "starkNet_declareContract",
+ "summary": "Declare contract",
+ "paramStructure": "by-name",
+ "params": [
+ {
+ "name": "senderAddress",
+ "summary": "Address of the account contract",
+ "description": "Address of the account contract",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/ADDRESS"
+ }
+ },
+ {
+ "name": "chainId",
+ "summary": "Id of the target Starknet network",
+ "description": "Id of the target Starknet network (default to Starknet Goerli Testnet)",
+ "required": false,
+ "schema": {
+ "$ref": "#/components/schemas/CHAIN_ID"
+ }
+ },
+ {
+ "name": "contractPayload",
+ "summary": "Payload of the contract",
+ "description": "Object that consist of contract payload",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/CONTRACT_PAYLOAD"
+ }
+ },
+ {
+ "name": "invocationDetails",
+ "summary": "Transaction configurate parameters",
+ "description": "A struct consist of maxFee, nonce and version",
+ "required": false,
+ "schema": {
+ "$ref": "#/components/schemas/INVOCATION_DETAILS"
+ }
+ }
+ ],
+ "result": {
+ "name": "result",
+ "summary": "Transaction result",
+ "description": "Transaction result consist of transaction hash and class hash",
+ "schema": {
+ "$ref": "#/components/schemas/DECLARE_CONTRACT_RESULT"
+ }
+ },
+ "errors": []
+ },
+ {
+ "name": "starkNet_signTransaction",
+ "summary": "Sign transaction",
+ "paramStructure": "by-name",
+ "params": [
+ {
+ "name": "signerAddress",
+ "summary": "Address of the account contract",
+ "description": "Address of the account contract",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/ADDRESS"
+ }
+ },
+ {
+ "name": "chainId",
+ "summary": "Id of the target Starknet network",
+ "description": "Id of the target Starknet network (default to Starknet Goerli Testnet)",
+ "required": false,
+ "schema": {
+ "$ref": "#/components/schemas/CHAIN_ID"
+ }
+ },
+ {
+ "name": "transactions",
+ "summary": "List of calldata payload",
+ "description": "List of calldata payload",
+ "required": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/CALLDATA"
+ }
+ }
+ },
+ {
+ "name": "abis",
+ "summary": "abis",
+ "description": "Array or Object that consist of abi",
+ "required": false,
+ "schema": {
+ "$ref": "#/components/schemas/ABIS"
+ }
+ },
+ {
+ "name": "transactionsDetail",
+ "summary": "Transaction Sign configurate parameters",
+ "description": "A struct consist of maxFee, nonce, version, walletAddress, chainId and cairoVersion",
+ "required": false,
+ "schema": {
+ "$ref": "#/components/schemas/SIGNER_INVOCATION_DETAILS"
+ }
+ }
+ ],
+ "result": {
+ "name": "result",
+ "summary": "Sign Transaction result",
+ "description": "Sign Transaction result consist of list of string",
+ "schema": {
+ "type": "array"
+ }
+ },
+ "errors": []
+ },
+ {
+ "name": "starkNet_signDeclareTransaction",
+ "summary": "Sign Declare transaction",
+ "paramStructure": "by-name",
+ "params": [
+ {
+ "name": "signerAddress",
+ "summary": "Address of the account contract",
+ "description": "Address of the account contract",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/ADDRESS"
+ }
+ },
+ {
+ "name": "chainId",
+ "summary": "Id of the target Starknet network",
+ "description": "Id of the target Starknet network (default to Starknet Goerli Testnet)",
+ "required": false,
+ "schema": {
+ "$ref": "#/components/schemas/CHAIN_ID"
+ }
+ },
+ {
+ "name": "transaction",
+ "summary": "Declare transaction payload",
+ "description": "Declare transaction payload",
+ "required": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/DECLARE_TRANSACTION_PAYLOAD"
+ }
+ }
+ }
+ ],
+ "result": {
+ "name": "result",
+ "summary": "Sign Transaction result",
+ "description": "Sign Transaction result consist of list of string",
+ "schema": {
+ "type": "array"
+ }
+ },
+ "errors": []
+ },
+ {
+ "name": "starkNet_signDeployAccountTransaction",
+ "summary": "Sign Deploy Account transaction",
+ "paramStructure": "by-name",
+ "params": [
+ {
+ "name": "signerAddress",
+ "summary": "Address of the account contract",
+ "description": "Address of the account contract",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/ADDRESS"
+ }
+ },
+ {
+ "name": "chainId",
+ "summary": "Id of the target Starknet network",
+ "description": "Id of the target Starknet network (default to Starknet Goerli Testnet)",
+ "required": false,
+ "schema": {
+ "$ref": "#/components/schemas/CHAIN_ID"
+ }
+ },
+ {
+ "name": "transaction",
+ "summary": "Deploy Account transaction payload",
+ "description": "DecDeploy Accountlare transaction payload",
+ "required": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/DEPLOY_ACCOUNT_TRANSACTION_PAYLOAD"
+ }
+ }
+ }
+ ],
+ "result": {
+ "name": "result",
+ "summary": "Sign Transaction result",
+ "description": "Sign Transaction result consist of list of string",
+ "schema": {
+ "type": "array"
+ }
+ },
+ "errors": []
}
],
"components": {
@@ -868,6 +1189,156 @@
"type": "string",
"pattern": "^0x[a-fA-F0-9]+$"
},
+ "ABIS": {
+ "type": "array"
+ },
+ "CALLDATA": {
+ "type": "array"
+ },
+ "CONTRACT_PAYLOAD": {
+ "type": "object",
+ "properties": {
+ "contract": {
+ "type": "string"
+ },
+ "classHash": {
+ "type": "string"
+ },
+ "casm": {
+ "type": "object"
+ },
+ "compiledClassHash": {
+ "type": "string"
+ }
+ }
+ },
+ "DECLARE_TRANSACTION_PAYLOAD" : {
+ "type": "object",
+ "properties": {
+ "classHash": {
+ "type": "string"
+ },
+ "senderAddress": {
+ "$ref": "#/components/schemas/FELT"
+ },
+ "chainId": {
+ "$ref": "#/components/schemas/CHAIN_ID"
+ },
+ "maxFee": {
+ "type": "integer"
+ },
+ "nonce": {
+ "type": "integer"
+ },
+ "version": {
+ "type": "integer"
+ },
+ "compiledClassHash": {
+ "type": "string"
+ }
+ }
+ },
+ "DEPLOY_ACCOUNT_TRANSACTION_PAYLOAD" : {
+ "type": "object",
+ "properties": {
+ "classHash": {
+ "type": "string"
+ },
+ "contractAddress": {
+ "$ref": "#/components/schemas/FELT"
+ },
+ "constructorCalldata": {
+ "type": "array"
+ },
+ "addressSalt": {
+ "type": "string"
+ },
+ "chainId": {
+ "$ref": "#/components/schemas/CHAIN_ID"
+ },
+ "maxFee": {
+ "type": "integer"
+ },
+ "nonce": {
+ "type": "integer"
+ },
+ "version": {
+ "type": "integer"
+ },
+ "compiledClassHash": {
+ "type": "string"
+ }
+ }
+ },
+ "INVOCATION_PAYLOAD": {
+ "type": "object",
+ "properties": {
+ "entrypoint": {
+ "type": "string"
+ },
+ "contractAddress": {
+ "$ref": "#/components/schemas/FELT"
+ },
+ "calldata": {
+ "$ref": "#/components/schemas/CALLDATA"
+ }
+ }
+ },
+ "INVOCATION": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": ["DECLARE", "DEPLOY", "DEPLOY_ACCOUNT", "INVOKE_FUNCTION"]
+ },
+ "payload": {
+ "$ref": "#/components/schemas/INVOCATION_PAYLOAD"
+ }
+ }
+ },
+ "INVOCATIONS": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/INVOCATION"
+ }
+ },
+ "INVOCATION_DETAILS": {
+ "type": "object",
+ "properties": {
+ "maxFee": {
+ "type": "integer"
+ },
+ "nonce": {
+ "type": "integer"
+ },
+ "version": {
+ "type": "integer"
+ }
+ }
+ },
+ "SIGNER_INVOCATION_DETAILS": {
+ "type": "object",
+ "properties": {
+ "maxFee": {
+ "type": "integer"
+ },
+ "nonce": {
+ "type": "integer"
+ },
+ "version": {
+ "type": "integer"
+ },
+ "walletAddress": {
+ "type": "string"
+ },
+ "chainId": {
+ "type": "string"
+ },
+ "cairoVersion": {
+ "type": "string"
+ }
+ }
+ },
"ADDRESS": {
"$ref": "#/components/schemas/FELT"
},
@@ -882,6 +1353,11 @@
"description": "The transaction hash, as assigned in Starknet",
"title": "A transaction's hash"
},
+ "CLASS_HASH": {
+ "$ref": "#/components/schemas/FELT",
+ "description": "The class hash, as assigned in Starknet",
+ "title": "A class's hash"
+ },
"FELT": {
"type": "string",
"title": "Field element",
@@ -899,30 +1375,17 @@
},
"TXN_STATUS": {
"type": "string",
- "enum": [
- "UNKNOWN",
- "RECEIVED",
- "PENDING",
- "ACCEPTED_ON_L2",
- "ACCEPTED_ON_L1",
- "REJECTED"
- ],
+ "enum": ["UNKNOWN", "RECEIVED", "PENDING", "ACCEPTED_ON_L2", "ACCEPTED_ON_L1", "REJECTED"],
"description": "The status of the transaction. May be unknown in case node is not aware of it"
},
"VOYAGER_TXN_TYPE": {
"type": "string",
- "enum": [
- "invoke",
- "deploy"
- ],
+ "enum": ["invoke", "deploy"],
"description": "The txn type of the transaction from Voyager. May not be a full list here and subject to change"
},
"VOYAGER_TXN_STATUS": {
"type": "string",
- "enum": [
- "Accepted on L2",
- "Accepted on L1"
- ],
+ "enum": ["Accepted on L2", "Accepted on L1"],
"description": "The status of the transaction. May be unknown in case node is not aware of it"
},
"TYPED_DATA_SIGNATURE": {
@@ -1093,16 +1556,25 @@
}
}
},
- "SEND_TRANSACTION_RESULT": {
+ "DECLARE_CONTRACT_RESULT": {
"type": "object",
"properties": {
"transaction_hash": {
"$ref": "#/components/schemas/TXN_HASH",
"description": "The hash identifying the transaction"
},
- "code": {
- "type": "string",
- "description": "Response code of the sent txn"
+ "class_hash": {
+ "$ref": "#/components/schemas/CLASS_HASH",
+ "description": "The hash identifying the class"
+ }
+ }
+ },
+ "SEND_TRANSACTION_RESULT": {
+ "type": "object",
+ "properties": {
+ "transaction_hash": {
+ "$ref": "#/components/schemas/TXN_HASH",
+ "description": "The hash identifying the transaction"
}
}
},
@@ -1143,6 +1615,30 @@
}
}
},
+ "ESTIMATE_FEE_RESULTS": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "suggestedMaxFee": {
+ "type": "string",
+ "description": "Estimated gas fee with overhead added in decimal string"
+ },
+ "overallFee": {
+ "type": "string",
+ "description": "Overall gas fee in in decimal string"
+ },
+ "gasConsumed": {
+ "type": "string",
+ "description": "Total amount of consumed gas in decimal string"
+ },
+ "gasPrice": {
+ "type": "string",
+ "description": "Price for each gas unit in decimal string"
+ }
+ }
+ }
+ },
"ADD_ERC_20_TOKEN_RESULT": {
"$ref": "#/components/schemas/ERC_20_TOKEN"
},
diff --git a/packages/starknet-snap/package.json b/packages/starknet-snap/package.json
index 44b0398a..1a9f72a7 100644
--- a/packages/starknet-snap/package.json
+++ b/packages/starknet-snap/package.json
@@ -17,6 +17,7 @@
"watch:snap": "mm-snap watch",
"prettier": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"lint": "eslint . --max-warnings 0 -f json -o eslint-report.json",
+ "lint:fix": "eslint '**/*.{js,ts,tsx}' --fix",
"test": "yarn run test:unit && yarn run cover:report",
"test:unit": "nyc --check-coverage --statements 80 --branches 80 --functions 80 --lines 80 mocha --colors -r ts-node/register \"test/**/*.test.ts\"",
"cover:report": "nyc report --reporter=lcov --reporter=text"
diff --git a/packages/starknet-snap/src/addErc20Token.ts b/packages/starknet-snap/src/addErc20Token.ts
index 72f5e22b..62e18c82 100644
--- a/packages/starknet-snap/src/addErc20Token.ts
+++ b/packages/starknet-snap/src/addErc20Token.ts
@@ -6,10 +6,11 @@ import {
upsertErc20Token,
getValidNumber,
validateAddErc20TokenParams,
+ getAddTokenText,
} from './utils/snapUtils';
import { DEFAULT_DECIMAL_PLACES } from './utils/constants';
import { DialogType } from '@metamask/rpc-methods';
-import { heading, panel, text, copyable } from '@metamask/snaps-ui';
+import { heading, panel } from '@metamask/snaps-ui';
import { logger } from './utils/logger';
export async function addErc20Token(params: ApiParams) {
@@ -37,16 +38,7 @@ export async function addErc20Token(params: ApiParams) {
type: DialogType.Confirmation,
content: panel([
heading('Do you want to add this token?'),
- text('**Token Address:**'),
- copyable(tokenAddress),
- text('**Token Name:**'),
- copyable(tokenName),
- text('**Token Symbol:**'),
- copyable(tokenSymbol),
- text('**Token Decimals:**'),
- copyable(tokenDecimals.toString()),
- text('**Network:**'),
- copyable(network.name),
+ ...getAddTokenText(tokenAddress, tokenName, tokenSymbol, tokenDecimals, network),
]),
},
});
diff --git a/packages/starknet-snap/src/addNetwork.ts b/packages/starknet-snap/src/addNetwork.ts
index 8e743a87..8f92f2be 100644
--- a/packages/starknet-snap/src/addNetwork.ts
+++ b/packages/starknet-snap/src/addNetwork.ts
@@ -1,11 +1,14 @@
import { toJson } from './utils/serializer';
import { AddNetworkRequestParams, ApiParams } from './types/snapApi';
-import { validateAddNetworkParams } from './utils/snapUtils';
+import { validateAddNetworkParams, upsertNetwork, getNetworkTxt } from './utils/snapUtils';
import { logger } from './utils/logger';
+import { Network } from './types/snapState';
+import { DialogType } from '@metamask/rpc-methods';
+import { panel, heading } from '@metamask/snaps-ui';
export async function addNetwork(params: ApiParams) {
try {
- const { requestParams } = params;
+ const { state, wallet, saveMutex, requestParams } = params;
const requestParamsObj = requestParams as AddNetworkRequestParams;
if (
@@ -22,7 +25,28 @@ export async function addNetwork(params: ApiParams) {
validateAddNetworkParams(requestParamsObj);
- throw new Error('addNetwork is currently disabled');
+ const network = {
+ name: requestParamsObj.networkName,
+ chainId: requestParamsObj.networkChainId,
+ baseUrl: requestParamsObj.networkBaseUrl,
+ nodeUrl: requestParamsObj.networkNodeUrl,
+ voyagerUrl: requestParamsObj.networkVoyagerUrl,
+ } as Network;
+
+ const components = getNetworkTxt(network);
+
+ const response = await wallet.request({
+ method: 'snap_dialog',
+ params: {
+ type: DialogType.Confirmation,
+ content: panel([heading('Do you want to add this network?'), ...components]),
+ },
+ });
+ if (!response) return false;
+
+ await upsertNetwork(network, wallet, saveMutex, state);
+
+ return true;
} catch (err) {
logger.error(`Problem found: ${err}`);
throw err;
diff --git a/packages/starknet-snap/src/createAccount.ts b/packages/starknet-snap/src/createAccount.ts
index 51546ea2..2bbe61df 100644
--- a/packages/starknet-snap/src/createAccount.ts
+++ b/packages/starknet-snap/src/createAccount.ts
@@ -13,6 +13,7 @@ import {
getValidNumber,
upsertAccount,
upsertTransaction,
+ addDialogTxt,
} from './utils/snapUtils';
import { AccContract, VoyagerTransactionType, Transaction, TransactionStatus } from './types/snapState';
import { ApiParams, CreateAccountRequestParams } from './types/snapApi';
@@ -38,10 +39,7 @@ export async function createAccount(params: ApiParams, silentMode = false) {
derivationPath,
} = await getKeysFromAddressIndex(keyDeriver, network.chainId, state, addressIndex);
- const { address: contractAddress, callData: contractCallData } = getAccContractAddressAndCallData(
- network.accountClassHash,
- publicKey,
- );
+ const { address: contractAddress, callData: contractCallData } = getAccContractAddressAndCallData(publicKey);
logger.log(
`createAccount:\ncontractAddress = ${contractAddress}\npublicKey = ${publicKey}\naddressIndex = ${addressIndexInUsed}`,
@@ -52,6 +50,11 @@ export async function createAccount(params: ApiParams, silentMode = false) {
if (deploy) {
if (!silentMode) {
+ const components = [];
+ addDialogTxt(components, 'Address', contractAddress);
+ addDialogTxt(components, 'Public Key', publicKey);
+ addDialogTxt(components, 'Address Index', addressIndex.toString());
+
const response = await wallet.request({
method: 'snap_dialog',
params: {
@@ -59,9 +62,7 @@ export async function createAccount(params: ApiParams, silentMode = false) {
content: panel([
heading('Do you want to sign this deploy account transaction ?'),
text(`It will be signed with address: ${contractAddress}`),
- text(
- `Account Info:\n\nAddress: ${contractAddress}\n\nPublic Key: ${publicKey}\n\nAddress Index: ${addressIndex}`,
- ),
+ ...components,
]),
},
});
diff --git a/packages/starknet-snap/src/declareContract.ts b/packages/starknet-snap/src/declareContract.ts
new file mode 100644
index 00000000..6a2e7028
--- /dev/null
+++ b/packages/starknet-snap/src/declareContract.ts
@@ -0,0 +1,48 @@
+import { toJson } from './utils/serializer';
+import { ApiParams, DeclareContractRequestParams } from './types/snapApi';
+import { getNetworkFromChainId, getDeclareSnapTxt } from './utils/snapUtils';
+import { getKeysFromAddress, declareContract as declareContractUtil } from './utils/starknetUtils';
+import { DialogType } from '@metamask/rpc-methods';
+import { heading, panel } from '@metamask/snaps-ui';
+import { logger } from './utils/logger';
+
+export async function declareContract(params: ApiParams) {
+ try {
+ const { state, keyDeriver, requestParams, wallet } = params;
+ const requestParamsObj = requestParams as DeclareContractRequestParams;
+
+ logger.log(`executeTxn params: ${toJson(requestParamsObj, 2)}}`);
+
+ const senderAddress = requestParamsObj.senderAddress;
+ const network = getNetworkFromChainId(state, requestParamsObj.chainId);
+ const { privateKey } = await getKeysFromAddress(keyDeriver, network, state, senderAddress);
+
+ const snapComponents = getDeclareSnapTxt(
+ senderAddress,
+ network,
+ requestParamsObj.contractPayload,
+ requestParamsObj.invocationsDetails,
+ );
+
+ const response = await wallet.request({
+ method: 'snap_dialog',
+ params: {
+ type: DialogType.Confirmation,
+ content: panel([heading('Do you want to sign this transaction?'), ...snapComponents]),
+ },
+ });
+
+ if (!response) return false;
+
+ return await declareContractUtil(
+ network,
+ senderAddress,
+ privateKey,
+ requestParamsObj.contractPayload,
+ requestParamsObj.invocationsDetails,
+ );
+ } catch (err) {
+ logger.error(`Problem found: ${err}`);
+ throw err;
+ }
+}
diff --git a/packages/starknet-snap/src/estimateAccountDeployFee.ts b/packages/starknet-snap/src/estimateAccountDeployFee.ts
index ecba799a..e60d5352 100644
--- a/packages/starknet-snap/src/estimateAccountDeployFee.ts
+++ b/packages/starknet-snap/src/estimateAccountDeployFee.ts
@@ -22,10 +22,7 @@ export async function estimateAccDeployFee(params: ApiParams) {
addressIndex: addressIndexInUsed,
privateKey,
} = await getKeysFromAddressIndex(keyDeriver, network.chainId, state, addressIndex);
- const { address: contractAddress, callData: contractCallData } = getAccContractAddressAndCallData(
- network.accountClassHash,
- publicKey,
- );
+ const { address: contractAddress, callData: contractCallData } = getAccContractAddressAndCallData(publicKey);
logger.log(
`estimateAccountDeployFee:\ncontractAddress = ${contractAddress}\npublicKey = ${publicKey}\naddressIndex = ${addressIndexInUsed}`,
);
diff --git a/packages/starknet-snap/src/estimateFee.ts b/packages/starknet-snap/src/estimateFee.ts
index 13f376dc..987b9de2 100644
--- a/packages/starknet-snap/src/estimateFee.ts
+++ b/packages/starknet-snap/src/estimateFee.ts
@@ -13,7 +13,7 @@ import {
isAccountDeployed,
isUpgradeRequired,
} from './utils/starknetUtils';
-
+import { ACCOUNT_CLASS_HASH_V1 } from './utils/constants';
import { logger } from './utils/logger';
export async function estimateFee(params: ApiParams) {
@@ -73,9 +73,10 @@ export async function estimateFee(params: ApiParams) {
},
];
if (!accountDeployed) {
- const { callData } = getAccContractAddressAndCallData(network.accountClassHash, publicKey);
+ const { callData } = getAccContractAddressAndCallData(publicKey);
+
const deployAccountpayload = {
- classHash: network.accountClassHash,
+ classHash: ACCOUNT_CLASS_HASH_V1,
contractAddress: senderAddress,
constructorCalldata: callData,
addressSalt: publicKey,
diff --git a/packages/starknet-snap/src/estimateFees.ts b/packages/starknet-snap/src/estimateFees.ts
new file mode 100644
index 00000000..624bbd5a
--- /dev/null
+++ b/packages/starknet-snap/src/estimateFees.ts
@@ -0,0 +1,36 @@
+import { toJson } from './utils/serializer';
+import { getNetworkFromChainId } from './utils/snapUtils';
+import { getKeysFromAddress, estimateFeeBulk } from './utils/starknetUtils';
+import { ApiParams, EstimateFeesRequestParams } from './types/snapApi';
+import { logger } from './utils/logger';
+
+export async function estimateFees(params: ApiParams) {
+ try {
+ const { state, keyDeriver, requestParams } = params;
+ const requestParamsObj = requestParams as EstimateFeesRequestParams;
+
+ logger.log(`estimateFees params: ${toJson(requestParamsObj, 2)}`);
+
+ const senderAddress = requestParamsObj.senderAddress;
+ const network = getNetworkFromChainId(state, requestParamsObj.chainId);
+ const { privateKey: senderPrivateKey } = await getKeysFromAddress(keyDeriver, network, state, senderAddress);
+
+ const fees = await estimateFeeBulk(
+ network,
+ senderAddress,
+ senderPrivateKey,
+ requestParamsObj.invocations,
+ requestParamsObj.invocationDetails ? requestParamsObj.invocationDetails : undefined,
+ );
+
+ return fees.map((fee) => ({
+ overall_fee: fee.overall_fee.toString(10) || '0',
+ gas_consumed: fee.gas_consumed.toString(10) || '0',
+ gas_price: fee.gas_price.toString(10) || '0',
+ suggestedMaxFee: fee.suggestedMaxFee.toString(10) || '0',
+ }));
+ } catch (err) {
+ logger.error(`Problem found: ${err}`);
+ throw err;
+ }
+}
diff --git a/packages/starknet-snap/src/executeTxn.ts b/packages/starknet-snap/src/executeTxn.ts
new file mode 100644
index 00000000..e6b8958a
--- /dev/null
+++ b/packages/starknet-snap/src/executeTxn.ts
@@ -0,0 +1,50 @@
+import { toJson } from './utils/serializer';
+import { getNetworkFromChainId, getTxnSnapTxt } from './utils/snapUtils';
+import { getKeysFromAddress, executeTxn as executeTxnUtil } from './utils/starknetUtils';
+import { ApiParams, ExecuteTxnRequestParams } from './types/snapApi';
+import { DialogType } from '@metamask/rpc-methods';
+import { heading, panel } from '@metamask/snaps-ui';
+import { logger } from './utils/logger';
+
+export async function executeTxn(params: ApiParams) {
+ try {
+ const { state, keyDeriver, requestParams, wallet } = params;
+ const requestParamsObj = requestParams as ExecuteTxnRequestParams;
+
+ logger.log(`executeTxn params: ${toJson(requestParamsObj, 2)}}`);
+
+ const senderAddress = requestParamsObj.senderAddress;
+ const network = getNetworkFromChainId(state, requestParamsObj.chainId);
+ const { privateKey: senderPrivateKey } = await getKeysFromAddress(keyDeriver, network, state, senderAddress);
+
+ const snapComponents = getTxnSnapTxt(
+ senderAddress,
+ network,
+ requestParamsObj.txnInvocation,
+ requestParamsObj.abis,
+ requestParamsObj.invocationsDetails,
+ );
+
+ const response = await wallet.request({
+ method: 'snap_dialog',
+ params: {
+ type: DialogType.Confirmation,
+ content: panel([heading('Do you want to sign this transaction(s)?'), ...snapComponents]),
+ },
+ });
+
+ if (!response) return false;
+
+ return await executeTxnUtil(
+ network,
+ senderAddress,
+ senderPrivateKey,
+ requestParamsObj.txnInvocation,
+ requestParamsObj.abis,
+ requestParamsObj.invocationsDetails,
+ );
+ } catch (err) {
+ logger.error(`Problem found: ${err}`);
+ throw err;
+ }
+}
diff --git a/packages/starknet-snap/src/getCurrentNetwork.ts b/packages/starknet-snap/src/getCurrentNetwork.ts
new file mode 100644
index 00000000..f85d1c4f
--- /dev/null
+++ b/packages/starknet-snap/src/getCurrentNetwork.ts
@@ -0,0 +1,16 @@
+import { toJson } from './utils/serializer';
+import { ApiParams } from './types/snapApi';
+import { getCurrentNetwork as getCurrentNetworkUtil } from './utils/snapUtils';
+import { logger } from './utils/logger';
+
+export async function getCurrentNetwork(params: ApiParams) {
+ try {
+ const { state } = params;
+ const networks = getCurrentNetworkUtil(state);
+ logger.log(`getCurrentNetwork: networks:\n${toJson(networks, 2)}`);
+ return networks;
+ } catch (err) {
+ logger.error(`Problem found: ${err}`);
+ throw err;
+ }
+}
diff --git a/packages/starknet-snap/src/index.ts b/packages/starknet-snap/src/index.ts
index 38ef0038..f2fd8910 100644
--- a/packages/starknet-snap/src/index.ts
+++ b/packages/starknet-snap/src/index.ts
@@ -2,6 +2,7 @@ import { toJson } from './utils/serializer';
import { getAddressKeyDeriver } from './utils/keyPair';
import { createAccount } from './createAccount';
import { signMessage } from './signMessage';
+import { signTransaction } from './signTransaction';
import { getErc20TokenBalance } from './getErc20TokenBalance';
import { getTransactionStatus } from './getTransactionStatus';
import { sendTransaction } from './sendTransaction';
@@ -15,6 +16,8 @@ import { SnapState } from './types/snapState';
import { extractPrivateKey } from './extractPrivateKey';
import { extractPublicKey } from './extractPublicKey';
import { addNetwork } from './addNetwork';
+import { switchNetwork } from './switchNetwork';
+import { getCurrentNetwork } from './getCurrentNetwork';
import {
PRELOADED_TOKENS,
STARKNET_INTEGRATION_NETWORK,
@@ -30,6 +33,11 @@ import { Mutex } from 'async-mutex';
import { OnRpcRequestHandler } from '@metamask/snaps-types';
import { ApiParams, ApiRequestParams } from './types/snapApi';
import { estimateAccDeployFee } from './estimateAccountDeployFee';
+import { executeTxn } from './executeTxn';
+import { estimateFees } from './estimateFees';
+import { declareContract } from './declareContract';
+import { signDeclareTransaction } from './signDeclareTransaction';
+import { signDeployAccountTransaction } from './signDeployAccountTransaction';
import { logger } from './utils/logger';
declare const snap;
@@ -113,6 +121,18 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ origin, request }) =>
apiParams.keyDeriver = await getAddressKeyDeriver(snap);
return signMessage(apiParams);
+ case 'starkNet_signTransaction':
+ apiParams.keyDeriver = await getAddressKeyDeriver(snap);
+ return signTransaction(apiParams);
+
+ case 'starkNet_signDeclareTransaction':
+ apiParams.keyDeriver = await getAddressKeyDeriver(snap);
+ return signDeclareTransaction(apiParams);
+
+ case 'starkNet_signDeployAccountTransaction':
+ apiParams.keyDeriver = await getAddressKeyDeriver(snap);
+ return signDeployAccountTransaction(apiParams);
+
case 'starkNet_verifySignedMessage':
apiParams.keyDeriver = await getAddressKeyDeriver(snap);
return verifySignedMessage(apiParams);
@@ -147,6 +167,12 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ origin, request }) =>
case 'starkNet_addNetwork':
return addNetwork(apiParams);
+ case 'starkNet_switchNetwork':
+ return switchNetwork(apiParams);
+
+ case 'starkNet_getCurrentNetwork':
+ return getCurrentNetwork(apiParams);
+
case 'starkNet_getStoredNetworks':
return getStoredNetworks(apiParams);
@@ -160,6 +186,18 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ origin, request }) =>
apiParams.keyDeriver = await getAddressKeyDeriver(snap);
return recoverAccounts(apiParams);
+ case 'starkNet_executeTxn':
+ apiParams.keyDeriver = await getAddressKeyDeriver(snap);
+ return executeTxn(apiParams);
+
+ case 'starkNet_estimateFees':
+ apiParams.keyDeriver = await getAddressKeyDeriver(snap);
+ return estimateFees(apiParams);
+
+ case 'starkNet_declareContract':
+ apiParams.keyDeriver = await getAddressKeyDeriver(snap);
+ return declareContract(apiParams);
+
default:
throw new Error('Method not found.');
}
diff --git a/packages/starknet-snap/src/recoverAccounts.ts b/packages/starknet-snap/src/recoverAccounts.ts
index d33454f6..d50f9e4a 100644
--- a/packages/starknet-snap/src/recoverAccounts.ts
+++ b/packages/starknet-snap/src/recoverAccounts.ts
@@ -4,8 +4,6 @@ import { getKeysFromAddressIndex, getCorrectContractAddress, isUpgradeRequired }
import { getNetworkFromChainId, getValidNumber, upsertAccount } from './utils/snapUtils';
import { AccContract } from './types/snapState';
import { ApiParams, RecoverAccountsRequestParams } from './types/snapApi';
-import { DialogType } from '@metamask/rpc-methods';
-import { heading, panel, text } from '@metamask/snaps-ui';
import { logger } from './utils/logger';
export async function recoverAccounts(params: ApiParams) {
@@ -20,20 +18,6 @@ export async function recoverAccounts(params: ApiParams) {
logger.log(`recoverAccounts:\nstartIndex: ${startIndex}, maxScanned: ${maxScanned}, maxMissed: ${maxMissed}`);
- if (!network.accountClassHash) {
- await wallet.request({
- method: 'snap_dialog',
- params: {
- type: DialogType.Alert,
- content: panel([
- heading('Failed to recover accounts'),
- text('Recover Accounts not supported in network without class hash'),
- ]),
- },
- });
- return null;
- }
-
let i = startIndex,
j = 0;
const scannedAccounts: AccContract[] = [];
diff --git a/packages/starknet-snap/src/sendTransaction.ts b/packages/starknet-snap/src/sendTransaction.ts
index 7ecf1fca..5c9ee72b 100644
--- a/packages/starknet-snap/src/sendTransaction.ts
+++ b/packages/starknet-snap/src/sendTransaction.ts
@@ -3,7 +3,7 @@ import { num, constants } from 'starknet';
import { validateAndParseAddress } from '../src/utils/starknetUtils';
import { estimateFee } from './estimateFee';
import { Transaction, TransactionStatus, VoyagerTransactionType } from './types/snapState';
-import { getNetworkFromChainId, getSigningTxnText, upsertTransaction } from './utils/snapUtils';
+import { getNetworkFromChainId, getSendTxnText, upsertTransaction } from './utils/snapUtils';
import {
getKeysFromAddress,
getCallDataArray,
@@ -62,7 +62,7 @@ export async function sendTransaction(params: ApiParams) {
maxFee = num.toBigInt(suggestedMaxFee);
}
- const signingTxnComponents = getSigningTxnText(
+ const signingTxnComponents = getSendTxnText(
state,
contractAddress,
contractFuncName,
@@ -108,14 +108,10 @@ export async function sendTransaction(params: ApiParams) {
//In case this is the first transaction we assign a nonce of 1 to make sure it does after the deploy transaction
const nonceSendTransaction = accountDeployed ? undefined : 1;
- const txnResp = await executeTxn(
- network,
- senderAddress,
- senderPrivateKey,
- txnInvocation,
+ const txnResp = await executeTxn(network, senderAddress, senderPrivateKey, txnInvocation, undefined, {
maxFee,
- nonceSendTransaction,
- );
+ nonce: nonceSendTransaction,
+ });
logger.log(`sendTransaction:\ntxnResp: ${toJson(txnResp)}`);
diff --git a/packages/starknet-snap/src/signDeclareTransaction.ts b/packages/starknet-snap/src/signDeclareTransaction.ts
new file mode 100644
index 00000000..ab1f782f
--- /dev/null
+++ b/packages/starknet-snap/src/signDeclareTransaction.ts
@@ -0,0 +1,39 @@
+import { toJson } from './utils/serializer';
+import { Signature } from 'starknet';
+import { ApiParams, SignDeclareTransactionRequestParams } from './types/snapApi';
+import { getKeysFromAddress, signDeclareTransaction as signDeclareTransactionUtil } from './utils/starknetUtils';
+import { getNetworkFromChainId, getSignTxnTxt } from './utils/snapUtils';
+import { DialogType } from '@metamask/rpc-methods';
+import { heading, panel } from '@metamask/snaps-ui';
+import { logger } from './utils/logger';
+
+export async function signDeclareTransaction(params: ApiParams): Promise {
+ try {
+ const { state, keyDeriver, requestParams, wallet } = params;
+ const requestParamsObj = requestParams as SignDeclareTransactionRequestParams;
+ const signerAddress = requestParamsObj.signerAddress;
+ const network = getNetworkFromChainId(state, requestParamsObj.chainId);
+ const { privateKey } = await getKeysFromAddress(keyDeriver, network, state, signerAddress);
+
+ logger.log(`signDeclareTransaction params: ${toJson(requestParamsObj.transaction, 2)}}`);
+
+ const snapComponents = getSignTxnTxt(signerAddress, network, requestParamsObj.transaction);
+
+ if (requestParamsObj.enableAutherize === true) {
+ const response = await wallet.request({
+ method: 'snap_dialog',
+ params: {
+ type: DialogType.Confirmation,
+ content: panel([heading('Do you want to sign this transaction?'), ...snapComponents]),
+ },
+ });
+
+ if (!response) return false;
+ }
+
+ return await signDeclareTransactionUtil(privateKey, requestParamsObj.transaction);
+ } catch (error) {
+ logger.error(`Problem found: ${error}`);
+ throw error;
+ }
+}
diff --git a/packages/starknet-snap/src/signDeployAccountTransaction.ts b/packages/starknet-snap/src/signDeployAccountTransaction.ts
new file mode 100644
index 00000000..9b35a2e3
--- /dev/null
+++ b/packages/starknet-snap/src/signDeployAccountTransaction.ts
@@ -0,0 +1,42 @@
+import { toJson } from './utils/serializer';
+import { Signature } from 'starknet';
+import { ApiParams, SignDeployAccountTransactionRequestParams } from './types/snapApi';
+import {
+ getKeysFromAddress,
+ signDeployAccountTransaction as signDeployAccountTransactionUtil,
+} from './utils/starknetUtils';
+import { getNetworkFromChainId, getSignTxnTxt } from './utils/snapUtils';
+import { DialogType } from '@metamask/rpc-methods';
+import { heading, panel } from '@metamask/snaps-ui';
+import { logger } from '../src/utils/logger';
+
+export async function signDeployAccountTransaction(params: ApiParams): Promise {
+ try {
+ const { state, keyDeriver, requestParams, wallet } = params;
+ const requestParamsObj = requestParams as SignDeployAccountTransactionRequestParams;
+ const signerAddress = requestParamsObj.signerAddress;
+ const network = getNetworkFromChainId(state, requestParamsObj.chainId);
+ const { privateKey } = await getKeysFromAddress(keyDeriver, network, state, signerAddress);
+
+ logger.log(`signDeployAccountTransaction params: ${toJson(requestParamsObj.transaction, 2)}}`);
+
+ const snapComponents = getSignTxnTxt(signerAddress, network, requestParamsObj.transaction);
+
+ if (requestParamsObj.enableAutherize === true) {
+ const response = await wallet.request({
+ method: 'snap_dialog',
+ params: {
+ type: DialogType.Confirmation,
+ content: panel([heading('Do you want to sign this transaction?'), ...snapComponents]),
+ },
+ });
+
+ if (!response) return false;
+ }
+
+ return await signDeployAccountTransactionUtil(privateKey, requestParamsObj.transaction);
+ } catch (error) {
+ logger.error(`Problem found: ${error}`);
+ throw error;
+ }
+}
diff --git a/packages/starknet-snap/src/signMessage.ts b/packages/starknet-snap/src/signMessage.ts
index 1c4cf2ca..c881a140 100644
--- a/packages/starknet-snap/src/signMessage.ts
+++ b/packages/starknet-snap/src/signMessage.ts
@@ -1,11 +1,10 @@
import { toJson } from './utils/serializer';
-import typedDataExample from './typedData/typedDataExample.json';
-import { getTypedDataMessageSignature, getKeysFromAddress, isUpgradeRequired } from './utils/starknetUtils';
-import { getNetworkFromChainId } from './utils/snapUtils';
+import { signMessage as signMessageUtil, getKeysFromAddress, isUpgradeRequired } from './utils/starknetUtils';
+import { getNetworkFromChainId, addDialogTxt } from './utils/snapUtils';
import { ApiParams, SignMessageRequestParams } from './types/snapApi';
import { validateAndParseAddress } from '../src/utils/starknetUtils';
import { DialogType } from '@metamask/rpc-methods';
-import { heading, panel, copyable, text } from '@metamask/snaps-ui';
+import { heading, panel } from '@metamask/snaps-ui';
import { logger } from './utils/logger';
export async function signMessage(params: ApiParams) {
@@ -13,9 +12,7 @@ export async function signMessage(params: ApiParams) {
const { state, wallet, keyDeriver, requestParams } = params;
const requestParamsObj = requestParams as SignMessageRequestParams;
const signerAddress = requestParamsObj.signerAddress;
- const typedDataMessage = requestParamsObj.typedDataMessage
- ? JSON.parse(requestParamsObj.typedDataMessage)
- : typedDataExample;
+ const typedDataMessage = requestParamsObj.typedDataMessage;
const network = getNetworkFromChainId(state, requestParamsObj.chainId);
logger.log(`signMessage:\nsignerAddress: ${signerAddress}\ntypedDataMessage: ${toJson(typedDataMessage)}`);
@@ -34,30 +31,29 @@ export async function signMessage(params: ApiParams) {
throw new Error('Upgrade required');
}
- const response = await wallet.request({
- method: 'snap_dialog',
- params: {
- type: DialogType.Confirmation,
- content: panel([
- heading('Do you want to sign this message ?'),
- text(`**Message:**`),
- copyable(toJson(typedDataMessage)),
- text(`**Signer address:**`),
- copyable(`${signerAddress}`),
- ]),
- },
- });
- if (!response) return false;
+ const components = [];
+ addDialogTxt(components, 'Message', toJson(typedDataMessage));
+ addDialogTxt(components, 'Signer Address', signerAddress);
- const { privateKey: signerPrivateKey } = await getKeysFromAddress(keyDeriver, network, state, signerAddress);
+ if (requestParamsObj.enableAutherize === true) {
+ const response = await wallet.request({
+ method: 'snap_dialog',
+ params: {
+ type: DialogType.Confirmation,
+ content: panel([heading('Do you want to sign this message?'), ...components]),
+ },
+ });
+
+ if (!response) return false;
+ }
- const typedDataSignature = getTypedDataMessageSignature(signerPrivateKey, typedDataMessage, signerAddress);
+ const { privateKey: signerPrivateKey } = await getKeysFromAddress(keyDeriver, network, state, signerAddress);
- const result = typedDataSignature.toDERHex();
+ const typedDataSignature = signMessageUtil(signerPrivateKey, typedDataMessage, signerAddress);
- logger.log(`signMessage:\ntypedDataSignature: ${result}`);
+ logger.log(`signMessage:\ntypedDataSignature: ${toJson(typedDataSignature)}`);
- return result;
+ return typedDataSignature;
} catch (err) {
logger.error(`Problem found: ${err}`);
throw err;
diff --git a/packages/starknet-snap/src/signTransaction.ts b/packages/starknet-snap/src/signTransaction.ts
new file mode 100644
index 00000000..57991e3c
--- /dev/null
+++ b/packages/starknet-snap/src/signTransaction.ts
@@ -0,0 +1,46 @@
+import { toJson } from './utils/serializer';
+import { Signature } from 'starknet';
+import { ApiParams, SignTransactionRequestParams } from './types/snapApi';
+import { getKeysFromAddress, signTransactions } from './utils/starknetUtils';
+import { getNetworkFromChainId, getSignTxnTxt } from './utils/snapUtils';
+import { DialogType } from '@metamask/rpc-methods';
+import { heading, panel } from '@metamask/snaps-ui';
+import { logger } from '../src/utils/logger';
+
+export async function signTransaction(params: ApiParams): Promise {
+ try {
+ const { state, keyDeriver, requestParams, wallet } = params;
+ const requestParamsObj = requestParams as SignTransactionRequestParams;
+ const signerAddress = requestParamsObj.signerAddress;
+ const network = getNetworkFromChainId(state, requestParamsObj.chainId);
+ const { privateKey } = await getKeysFromAddress(keyDeriver, network, state, signerAddress);
+
+ logger.log(`signTransaction params: ${toJson(requestParamsObj.transactions, 2)}}`);
+
+ const snapComponents = getSignTxnTxt(signerAddress, network, requestParamsObj.transactions);
+
+ if (requestParamsObj.enableAutherize === true) {
+ const response = await wallet.request({
+ method: 'snap_dialog',
+ params: {
+ type: DialogType.Confirmation,
+ content: panel([heading('Do you want to sign this transaction?'), ...snapComponents]),
+ },
+ });
+
+ if (!response) return false;
+ }
+
+ const signatures = await signTransactions(
+ privateKey,
+ requestParamsObj.transactions,
+ requestParamsObj.transactionsDetail,
+ requestParamsObj.abis,
+ );
+
+ return signatures;
+ } catch (error) {
+ logger.error(`Problem found: ${error}`);
+ throw error;
+ }
+}
diff --git a/packages/starknet-snap/src/switchNetwork.ts b/packages/starknet-snap/src/switchNetwork.ts
new file mode 100644
index 00000000..1159710f
--- /dev/null
+++ b/packages/starknet-snap/src/switchNetwork.ts
@@ -0,0 +1,35 @@
+import { toJson } from './utils/serializer';
+import { ApiParams, SwitchNetworkRequestParams } from './types/snapApi';
+import { getNetwork, setCurrentNetwork, getNetworkTxt } from './utils/snapUtils';
+import { DialogType } from '@metamask/rpc-methods';
+import { panel, heading } from '@metamask/snaps-ui';
+import { logger } from './utils/logger';
+
+export async function switchNetwork(params: ApiParams) {
+ try {
+ const { state, wallet, saveMutex, requestParams } = params;
+ const requestParamsObj = requestParams as SwitchNetworkRequestParams;
+ const network = getNetwork(state, requestParamsObj.chainId);
+ if (!network) {
+ throw new Error(`The given chainId is invalid: ${requestParamsObj.chainId}`);
+ }
+ const components = getNetworkTxt(network);
+
+ const response = await wallet.request({
+ method: 'snap_dialog',
+ params: {
+ type: DialogType.Confirmation,
+ content: panel([heading('Do you want to switch to this network?'), ...components]),
+ },
+ });
+ if (!response) return false;
+
+ logger.log(`switchNetwork: network:\n${toJson(network, 2)}`);
+ await setCurrentNetwork(network, wallet, saveMutex, state);
+
+ return true;
+ } catch (err) {
+ logger.error(`Problem found: ${err}`);
+ throw err;
+ }
+}
diff --git a/packages/starknet-snap/src/types/snapApi.ts b/packages/starknet-snap/src/types/snapApi.ts
index 0273c95a..37f80539 100644
--- a/packages/starknet-snap/src/types/snapApi.ts
+++ b/packages/starknet-snap/src/types/snapApi.ts
@@ -1,6 +1,18 @@
import { BIP44AddressKeyDeriver } from '@metamask/key-tree';
import Mutex from 'async-mutex/lib/Mutex';
import { SnapState, VoyagerTransactionType } from './snapState';
+import {
+ Abi,
+ Call,
+ InvocationsSignerDetails,
+ DeclareContractPayload,
+ InvocationsDetails,
+ Invocations,
+ EstimateFeeDetails,
+ DeployAccountSignerDetails,
+ DeclareSignerDetails,
+ typedData,
+} from 'starknet';
export interface ApiParams {
state: SnapState;
@@ -29,7 +41,11 @@ export type ApiRequestParams =
| GetStoredNetworksRequestParams
| GetStoredTransactionsRequestParams
| GetTransactionsRequestParams
- | RecoverAccountsRequestParams;
+ | RecoverAccountsRequestParams
+ | ExecuteTxnRequestParams
+ | EstimateFeesRequestParams
+ | DeclareContractRequestParams
+ | SignTransactionRequestParams;
export interface BaseRequestParams {
chainId?: string;
@@ -59,9 +75,8 @@ export interface ExtractPublicKeyRequestParams extends BaseRequestParams {
userAddress: string;
}
-export interface SignMessageRequestParams extends BaseRequestParams {
- signerAddress: string;
- typedDataMessage?: string;
+export interface SignMessageRequestParams extends SignRequestParams, BaseRequestParams {
+ typedDataMessage: typedData.TypedData;
}
export interface VerifySignedMessageRequestParams extends BaseRequestParams {
@@ -142,7 +157,49 @@ export interface RecoverAccountsRequestParams extends BaseRequestParams {
maxMissed?: string | number;
}
+export interface ExecuteTxnRequestParams extends BaseRequestParams {
+ senderAddress: string;
+ txnInvocation: Call | Call[];
+ abis?: Abi[];
+ invocationsDetails?: InvocationsDetails;
+}
+
+export interface EstimateFeesRequestParams extends BaseRequestParams {
+ senderAddress: string;
+ invocations: Invocations;
+ invocationDetails?: EstimateFeeDetails;
+}
+
+export interface DeclareContractRequestParams extends BaseRequestParams {
+ senderAddress: string;
+ contractPayload: DeclareContractPayload;
+ invocationsDetails?: InvocationsDetails;
+}
+
export interface RpcV4GetTransactionReceiptResponse {
execution_status?: string;
finality_status?: string;
}
+
+export interface SignRequestParams {
+ signerAddress: string;
+ enableAutherize?: boolean;
+}
+
+export interface SignTransactionRequestParams extends SignRequestParams, BaseRequestParams {
+ transactions: Call[];
+ transactionsDetail: InvocationsSignerDetails;
+ abis?: Abi[];
+}
+
+export interface SignDeployAccountTransactionRequestParams extends SignRequestParams, BaseRequestParams {
+ transaction: DeployAccountSignerDetails;
+}
+
+export interface SignDeclareTransactionRequestParams extends SignRequestParams, BaseRequestParams {
+ transaction: DeclareSignerDetails;
+}
+
+export interface SwitchNetworkRequestParams extends BaseRequestParams {
+ chainId: string;
+}
diff --git a/packages/starknet-snap/src/types/snapState.ts b/packages/starknet-snap/src/types/snapState.ts
index b149e319..dca1e0c9 100644
--- a/packages/starknet-snap/src/types/snapState.ts
+++ b/packages/starknet-snap/src/types/snapState.ts
@@ -5,6 +5,7 @@ export interface SnapState {
erc20Tokens: Erc20Token[];
networks: Network[];
transactions: Transaction[];
+ currentNetwork?: Network;
}
export interface AccContract {
diff --git a/packages/starknet-snap/src/utils/constants.ts b/packages/starknet-snap/src/utils/constants.ts
index bc44de46..3b62bcdf 100644
--- a/packages/starknet-snap/src/utils/constants.ts
+++ b/packages/starknet-snap/src/utils/constants.ts
@@ -13,6 +13,9 @@ export const MAXIMUM_TOKEN_SYMBOL_LENGTH = 16;
export const TRANSFER_SELECTOR_HEX = '0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e';
+export const ACCOUNT_CLASS_HASH_V0 = '0x033434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2'; // from argent-x repo
+export const ACCOUNT_CLASS_HASH_V1 = '0x1a736d6ed154502257f02b1ccdf4d9d1089f80811cd6acad48e6b6a9d1f2003'; // from argent-x repo
+
export const STARKNET_MAINNET_NETWORK: Network = {
name: 'Starknet Mainnet',
chainId: constants.StarknetChainId.SN_MAIN,
diff --git a/packages/starknet-snap/src/utils/snapUtils.ts b/packages/starknet-snap/src/utils/snapUtils.ts
index 4d87f282..3bbe34dc 100644
--- a/packages/starknet-snap/src/utils/snapUtils.ts
+++ b/packages/starknet-snap/src/utils/snapUtils.ts
@@ -1,6 +1,14 @@
import { toJson } from './serializer';
import { Mutex } from 'async-mutex';
-import { num } from 'starknet';
+import {
+ num,
+ InvocationsDetails,
+ DeclareContractPayload,
+ Abi,
+ DeclareSignerDetails,
+ Call,
+ DeployAccountSignerDetails,
+} from 'starknet';
import { validateAndParseAddress } from './starknetUtils';
import { Component, text, copyable } from '@metamask/snaps-ui';
import {
@@ -71,26 +79,25 @@ function isValidNetworkName(networkName: string) {
function isPreloadedTokenName(tokenName: string, chainId: string) {
return !!PRELOADED_TOKENS.find(
- (token) => token.name.trim() === tokenName.trim() && Number(token.chainId) === Number(chainId),
+ (token) => token.name.trim() === tokenName.trim() && isSameChainId(token.chainId, chainId),
);
}
function isPreloadedTokenSymbol(tokenSymbol: string, chainId: string) {
return !!PRELOADED_TOKENS.find(
- (token) => token.symbol.trim() === tokenSymbol.trim() && Number(token.chainId) === Number(chainId),
+ (token) => token.symbol.trim() === tokenSymbol.trim() && isSameChainId(token.chainId, chainId),
);
}
function isPreloadedTokenAddress(tokenAddress: string, chainId: string) {
const bigIntTokenAddress = num.toBigInt(tokenAddress);
return !!PRELOADED_TOKENS.find(
- (token) => num.toBigInt(token.address) === bigIntTokenAddress && Number(token.chainId) === Number(chainId),
+ (token) => num.toBigInt(token.address) === bigIntTokenAddress && isSameChainId(token.chainId, chainId),
);
}
-function isPreloadedNetworkChainId(networkChainId: string) {
- const bigIntNetworkChainId = num.toBigInt(networkChainId);
- return !!PRELOADED_NETWORKS.find((network) => num.toBigInt(network.chainId) === bigIntNetworkChainId);
+function isPreloadedNetworkChainId(chainId: string) {
+ return !!PRELOADED_NETWORKS.find((network) => isSameChainId(network.chainId, chainId));
}
function isPreloadedNetworkName(networkName: string) {
@@ -150,14 +157,6 @@ export function validateAddNetworkParams(params: AddNetworkRequestParams) {
throw new Error(`The given network Voyager URL is not an valid HTTP/HTTPS URL: ${params.networkVoyagerUrl}`);
}
- if (params.accountClassHash) {
- try {
- validateAndParseAddress(params.accountClassHash);
- } catch (err) {
- throw new Error(`The given account class hash is invalid: ${params.accountClassHash}`);
- }
- }
-
if (isPreloadedNetworkChainId(params.networkChainId) || isPreloadedNetworkName(params.networkName)) {
throw new Error(
'The given network chainId or name is the same as one of the preloaded networks, and thus cannot be added',
@@ -165,6 +164,10 @@ export function validateAddNetworkParams(params: AddNetworkRequestParams) {
}
}
+export function isSameChainId(chainId1: string, chainId2: string) {
+ return num.toBigInt(chainId1) === num.toBigInt(chainId2);
+}
+
export const getValidNumber = (
obj,
defaultValue: number,
@@ -175,7 +178,55 @@ export const getValidNumber = (
return obj === '' || isNaN(toNum) || toNum > maxVal || toNum < minVal ? defaultValue : toNum;
};
-export function getSigningTxnText(
+export function addDialogTxt(components: Array, label: string, value: string) {
+ components.push(text(`**${label}:**`));
+ components.push(copyable(value));
+}
+
+export function getNetworkTxt(network: Network) {
+ const components = [];
+ addDialogTxt(components, 'Chain Name', network.name);
+ addDialogTxt(components, 'Chain ID', network.chainId);
+ if (network.baseUrl) {
+ addDialogTxt(components, 'Base URL', network.baseUrl);
+ }
+ if (network.nodeUrl) {
+ addDialogTxt(components, 'RPC URL', network.nodeUrl);
+ }
+ if (network.voyagerUrl) {
+ addDialogTxt(components, 'Explorer URL', network.voyagerUrl);
+ }
+ return components;
+}
+
+export function getTxnSnapTxt(
+ senderAddress: string,
+ network: Network,
+ txnInvocation: Call | Call[],
+ abis?: Abi[],
+ invocationsDetails?: InvocationsDetails,
+) {
+ const components = [];
+ addDialogTxt(components, 'Network', network.name);
+ addDialogTxt(components, 'Signer Address', senderAddress);
+ addDialogTxt(components, 'Transaction Invocation', JSON.stringify(txnInvocation, null, 2));
+ if (abis && abis.length > 0) {
+ addDialogTxt(components, 'Abis', JSON.stringify(abis, null, 2));
+ }
+
+ if (invocationsDetails?.maxFee) {
+ addDialogTxt(components, 'Max Fee(ETH)', convert(invocationsDetails.maxFee, 'wei', 'ether'));
+ }
+ if (invocationsDetails?.nonce) {
+ addDialogTxt(components, 'Nonce', invocationsDetails.nonce.toString());
+ }
+ if (invocationsDetails?.version) {
+ addDialogTxt(components, 'Version', invocationsDetails.version.toString());
+ }
+ return components;
+}
+
+export function getSendTxnText(
state: SnapState,
contractAddress: string,
contractFuncName: string,
@@ -186,8 +237,13 @@ export function getSigningTxnText(
): Array {
// Retrieve the ERC-20 token from snap state for confirmation display purpose
const token = getErc20Token(state, contractAddress, network.chainId);
- const tokenTransferComponents1 = [];
- const tokenTransferComponents2 = [];
+ const components = [];
+ addDialogTxt(components, 'Signer Address', senderAddress);
+ addDialogTxt(components, 'Contract', contractAddress);
+ addDialogTxt(components, 'Call Data', `[${contractCallData.join(', ')}]`);
+ addDialogTxt(components, 'Estimated Gas Fee(ETH)', convert(maxFee, 'wei', 'ether'));
+ addDialogTxt(components, 'Network', network.name);
+
if (token && contractFuncName === 'transfer') {
try {
let amount = '';
@@ -196,28 +252,65 @@ export function getSigningTxnText(
} else {
amount = (Number(contractCallData[1]) * Math.pow(10, -1 * token.decimals)).toFixed(token.decimals);
}
- tokenTransferComponents2.push(text('**Sender Address:**'));
- tokenTransferComponents2.push(copyable(senderAddress));
- tokenTransferComponents2.push(text('**Recipient Address:**'));
- tokenTransferComponents2.push(copyable(contractCallData[0]));
- tokenTransferComponents2.push(text(`**Amount(${token.symbol}):**`));
- tokenTransferComponents2.push(copyable(amount));
+ addDialogTxt(components, 'Sender Address', senderAddress);
+ addDialogTxt(components, 'Recipient Address', contractCallData[0]);
+ addDialogTxt(components, `Amount(${token.symbol})`, amount);
} catch (err) {
logger.error(`getSigningTxnText: error found in amount conversion: ${err}`);
}
}
- tokenTransferComponents1.push(text('**Signer Address:**'));
- tokenTransferComponents1.push(copyable(senderAddress));
- tokenTransferComponents1.push(text('**Contract:**'));
- tokenTransferComponents1.push(copyable(contractAddress));
- tokenTransferComponents1.push(text('**Call Data:**'));
- tokenTransferComponents1.push(copyable(`[${contractCallData.join(', ')}]`));
- tokenTransferComponents1.push(text('**Estimated Gas Fee(ETH):**'));
- tokenTransferComponents1.push(copyable(convert(maxFee, 'wei', 'ether')));
- tokenTransferComponents1.push(text('**Network:**'));
- tokenTransferComponents1.push(copyable(network.name));
- return tokenTransferComponents1.concat(tokenTransferComponents2);
+ return components;
+}
+
+export function getSignTxnTxt(
+ signerAddress: string,
+ network: Network,
+ txnInvocation: Call[] | DeclareSignerDetails | DeployAccountSignerDetails,
+) {
+ const components = [];
+ addDialogTxt(components, 'Network', network.name);
+ addDialogTxt(components, 'Signer Address', signerAddress);
+ addDialogTxt(components, 'Transaction', JSON.stringify(txnInvocation, null, 2));
+ return components;
+}
+
+export function getDeclareSnapTxt(
+ senderAddress: string,
+ network: Network,
+ contractPayload: DeclareContractPayload,
+ invocationsDetails?: InvocationsDetails,
+) {
+ const components = [];
+ addDialogTxt(components, 'Network', network.name);
+ addDialogTxt(components, 'Signer Address', senderAddress);
+
+ if (contractPayload.contract) {
+ const _contractPayload =
+ typeof contractPayload.contract === 'string' || contractPayload.contract instanceof String
+ ? contractPayload.contract.toString()
+ : JSON.stringify(contractPayload.contract, null, 2);
+ addDialogTxt(components, 'Contract', _contractPayload);
+ }
+ if (contractPayload.compiledClassHash) {
+ addDialogTxt(components, 'Complied Class Hash', contractPayload.compiledClassHash);
+ }
+ if (contractPayload.classHash) {
+ addDialogTxt(components, 'Class Hash', contractPayload.classHash);
+ }
+ if (contractPayload.casm) {
+ addDialogTxt(components, 'Casm', JSON.stringify(contractPayload.casm, null, 2));
+ }
+ if (invocationsDetails?.maxFee !== undefined) {
+ addDialogTxt(components, 'Max Fee(ETH)', convert(invocationsDetails.maxFee, 'wei', 'ether'));
+ }
+ if (invocationsDetails?.nonce !== undefined) {
+ addDialogTxt(components, 'Nonce', invocationsDetails.nonce.toString());
+ }
+ if (invocationsDetails?.version !== undefined) {
+ addDialogTxt(components, 'Version', invocationsDetails.version.toString());
+ }
+ return components;
}
export function getAddTokenText(
@@ -227,19 +320,25 @@ export function getAddTokenText(
tokenDecimals: number,
network: Network,
) {
- return `Token Address: ${tokenAddress}\n\nToken Name: ${tokenName}\n\nToken Symbol: ${tokenSymbol}\n\nToken Decimals: ${tokenDecimals}\n\nNetwork: ${network.name}`;
+ const components = [];
+ addDialogTxt(components, 'Network', network.name);
+ addDialogTxt(components, 'Token Address', tokenAddress);
+ addDialogTxt(components, 'Token Name', tokenName);
+ addDialogTxt(components, 'Token Symbol', tokenSymbol);
+ addDialogTxt(components, 'Token Decimals', tokenDecimals.toString());
+ return components;
}
export function getAccount(state: SnapState, accountAddress: string, chainId: string) {
const bigIntAccountAddress = num.toBigInt(accountAddress);
return state.accContracts?.find(
- (acc) => num.toBigInt(acc.address) === bigIntAccountAddress && Number(acc.chainId) === Number(chainId),
+ (acc) => num.toBigInt(acc.address) === bigIntAccountAddress && isSameChainId(acc.chainId, chainId),
);
}
export function getAccounts(state: SnapState, chainId: string) {
return state.accContracts
- .filter((acc) => Number(acc.chainId) === Number(chainId))
+ .filter((acc) => isSameChainId(acc.chainId, chainId))
.sort((a: AccContract, b: AccContract) => a.addressIndex - b.addressIndex);
}
@@ -285,7 +384,7 @@ export async function upsertAccount(userAccount: AccContract, wallet, mutex: Mut
export function getNetwork(state: SnapState, chainId: string) {
return state.networks?.find(
- (network) => Number(network.chainId) === Number(chainId) && !Boolean(network?.useOldAccounts),
+ (network) => isSameChainId(network.chainId, chainId) && !Boolean(network?.useOldAccounts),
);
}
@@ -319,7 +418,6 @@ export async function upsertNetwork(network: Network, wallet, mutex: Mutex, stat
storedNetwork.baseUrl = network.baseUrl;
storedNetwork.nodeUrl = network.nodeUrl;
storedNetwork.voyagerUrl = network.voyagerUrl;
- storedNetwork.accountClassHash = network.accountClassHash;
}
await wallet.request({
@@ -335,16 +433,16 @@ export async function upsertNetwork(network: Network, wallet, mutex: Mutex, stat
export function getErc20Token(state: SnapState, tokenAddress: string, chainId: string) {
const bigIntTokenAddress = num.toBigInt(tokenAddress);
return state.erc20Tokens?.find(
- (token) => num.toBigInt(token.address) === bigIntTokenAddress && Number(token.chainId) === Number(chainId),
+ (token) => num.toBigInt(token.address) === bigIntTokenAddress && isSameChainId(token.chainId, chainId),
);
}
export function getErc20Tokens(state: SnapState, chainId: string) {
- return state.erc20Tokens?.filter((token) => Number(token.chainId) === Number(chainId));
+ return state.erc20Tokens?.filter((token) => isSameChainId(token.chainId, chainId));
}
export function getEtherErc20Token(state: SnapState, chainId: string) {
- return state.erc20Tokens?.find((token) => Number(token.chainId) === Number(chainId) && token.symbol === 'ETH');
+ return state.erc20Tokens?.find((token) => isSameChainId(token.chainId, chainId) && token.symbol === 'ETH');
}
export async function upsertErc20Token(erc20Token: Erc20Token, wallet, mutex: Mutex, state: SnapState = undefined) {
@@ -397,7 +495,7 @@ export function getNetworkFromChainId(state: SnapState, targerChainId: string |
}
export function getChainIdHex(network: Network) {
- return `0x${Number(network.chainId).toString(16)}`;
+ return `0x${num.toBigInt(network.chainId).toString(16)}`;
}
export function getTransactionFromVoyagerUrl(network: Network) {
@@ -411,7 +509,7 @@ export function getTransactionsFromVoyagerUrl(network: Network) {
export function getTransaction(state: SnapState, txnHash: string, chainId: string) {
const bigIntTxnHash = num.toBigInt(txnHash);
return state.transactions?.find(
- (txn) => num.toBigInt(txn.txnHash) === bigIntTxnHash && Number(txn.chainId) === Number(chainId),
+ (txn) => num.toBigInt(txn.txnHash) === bigIntTxnHash && isSameChainId(txn.chainId, chainId),
);
}
@@ -428,7 +526,7 @@ export function getTransactions(
let filteredTxns: Transaction[] = [];
if (state.transactions) {
filteredTxns = filterTransactions(state.transactions, [
- new ChainIdFilter(Number(chainId)),
+ new ChainIdFilter(chainId),
new TimestampFilter(minTimestamp),
new SenderAddressFilter(senderAddress ? num.toBigInt(senderAddress) : undefined),
new ContractAddressFilter(contractAddress ? num.toBigInt(contractAddress) : undefined),
@@ -550,6 +648,33 @@ export async function removeAcceptedTransaction(
});
}
+export function getCurrentNetwork(state: SnapState) {
+ return state.currentNetwork || STARKNET_TESTNET_NETWORK;
+}
+
+export async function setCurrentNetwork(network: Network, wallet, mutex: Mutex, state: SnapState = undefined) {
+ return mutex.runExclusive(async () => {
+ if (!state) {
+ state = await wallet.request({
+ method: 'snap_manageState',
+ params: {
+ operation: 'get',
+ },
+ });
+ }
+
+ state.currentNetwork = network;
+
+ await wallet.request({
+ method: 'snap_manageState',
+ params: {
+ operation: 'update',
+ newState: state,
+ },
+ });
+ });
+}
+
export function toMap(arr: Array, key: string, keyConverter?: (v: z) => k): Map {
return arr.reduce((map, obj: v) => {
map.set(keyConverter && typeof keyConverter === 'function' ? keyConverter(obj[key] as z) : obj[key], obj);
diff --git a/packages/starknet-snap/src/utils/starknetUtils.ts b/packages/starknet-snap/src/utils/starknetUtils.ts
index d81fc05e..c06de763 100644
--- a/packages/starknet-snap/src/utils/starknetUtils.ts
+++ b/packages/starknet-snap/src/utils/starknetUtils.ts
@@ -21,10 +21,27 @@ import {
GetTransactionResponse,
Invocations,
validateAndParseAddress as _validateAndParseAddress,
+ EstimateFeeDetails,
+ DeclareContractPayload,
+ DeclareContractResponse,
+ InvocationsDetails,
+ Signer,
+ Signature,
+ stark,
+ InvocationsSignerDetails,
+ Abi,
+ DeclareSignerDetails,
+ DeployAccountSignerDetails,
} from 'starknet';
import type { Hex } from '@noble/curves/abstract/utils';
import { Network, SnapState, Transaction, TransactionType } from '../types/snapState';
-import { PROXY_CONTRACT_HASH, TRANSFER_SELECTOR_HEX, MIN_ACC_CONTRACT_VERSION } from './constants';
+import {
+ PROXY_CONTRACT_HASH,
+ TRANSFER_SELECTOR_HEX,
+ MIN_ACC_CONTRACT_VERSION,
+ ACCOUNT_CLASS_HASH_V0,
+ ACCOUNT_CLASS_HASH_V1,
+} from './constants';
import { getAddressKey } from './keyPair';
import { getAccount, getAccounts, getTransactionFromVoyagerUrl, getTransactionsFromVoyagerUrl } from './snapUtils';
import { logger } from './logger';
@@ -73,6 +90,18 @@ export const callContract = async (
);
};
+export const declareContract = async (
+ network: Network,
+ senderAddress: string,
+ privateKey: string | Uint8Array,
+ contractPayload: DeclareContractPayload,
+ transactionsDetail?: InvocationsDetails,
+): Promise => {
+ const provider = getProvider(network);
+ const account = new Account(provider, senderAddress, privateKey);
+ return account.declare(contractPayload, transactionsDetail);
+};
+
export const estimateFee = async (
network: Network,
senderAddress: string,
@@ -89,12 +118,13 @@ export const estimateFeeBulk = async (
senderAddress: string,
privateKey: string | Uint8Array,
txnInvocation: Invocations,
+ invocationsDetails: EstimateFeeDetails = { blockIdentifier: 'latest' },
): Promise => {
// ensure always calling the sequencer endpoint since the rpc endpoint and
// starknet.js are not supported yet.
const provider = getProvider(network);
const account = new Account(provider, senderAddress, privateKey, '1');
- return account.estimateFeeBulk(txnInvocation, { blockIdentifier: 'latest' });
+ return account.estimateFeeBulk(txnInvocation, invocationsDetails);
};
export const executeTxn = async (
@@ -102,12 +132,12 @@ export const executeTxn = async (
senderAddress: string,
privateKey: string | Uint8Array,
txnInvocation: Call | Call[],
- maxFee: num.BigNumberish,
- nonce?: number,
+ abis?: Abi[],
+ invocationsDetails?: InvocationsDetails,
): Promise => {
const provider = getProvider(network);
const account = new Account(provider, senderAddress, privateKey, '1');
- return account.execute(txnInvocation, undefined, { nonce, maxFee });
+ return account.execute(txnInvocation, abis, invocationsDetails);
};
export const deployAccount = async (
@@ -391,31 +421,26 @@ export const getNextAddressIndex = (chainId: string, state: SnapState, derivatio
return uninitializedAccount?.addressIndex ?? accounts.length;
};
-export const getAccContractAddressAndCallData = (accountClassHash: string, publicKey) => {
- const constructorCallData = {
+export const getAccContractAddressAndCallData = (publicKey) => {
+ const callData = CallData.compile({
signer: publicKey,
guardian: '0',
- };
+ });
- let address = hash.calculateContractAddressFromHash(
- constructorCallData.signer,
- accountClassHash,
- constructorCallData,
- 0,
- );
+ let address = hash.calculateContractAddressFromHash(publicKey, ACCOUNT_CLASS_HASH_V1, callData, 0);
if (address.length < 66) {
address = address.replace('0x', '0x' + '0'.repeat(66 - address.length));
}
return {
address,
- callData: CallData.compile(constructorCallData),
+ callData,
};
};
-export const getAccContractAddressAndCallDataCairo0 = (accountClassHash: string, publicKey) => {
+export const getAccContractAddressAndCallDataCairo0 = (publicKey) => {
const callData = CallData.compile({
- implementation: accountClassHash,
+ implementation: ACCOUNT_CLASS_HASH_V0,
selector: hash.getSelectorFromName('initialize'),
calldata: CallData.compile({ signer: publicKey, guardian: '0' }),
});
@@ -442,23 +467,10 @@ export const getKeysFromAddress = async (
addressIndex = acc.addressIndex;
logger.log(`getNextAddressIndex:\nFound address in state: ${addressIndex} ${address}`);
} else {
- const bigIntAddress = num.toBigInt(address);
- for (let i = 0; i < maxScan; i++) {
- const { publicKey } = await getKeysFromAddressIndex(keyDeriver, network.chainId, state, i);
- const { address: calculatedAddress } = getAccContractAddressAndCallData(network.accountClassHash, publicKey);
- if (num.toBigInt(calculatedAddress) === bigIntAddress) {
- addressIndex = i;
- logger.log(`getNextAddressIndex:\nFound address in scan: ${addressIndex} ${address}`);
- break;
- }
- }
- }
-
- if (!isNaN(addressIndex)) {
- return getKeysFromAddressIndex(keyDeriver, network.chainId, state, addressIndex);
+ const result = await findAddressIndex(network.chainId, address, keyDeriver, state, maxScan);
+ addressIndex = result.index;
}
- logger.log(`getNextAddressIndex:\nAddress not found: ${address}`);
- throw new Error(`Address not found: ${address}`);
+ return getKeysFromAddressIndex(keyDeriver, network.chainId, state, addressIndex);
};
export const getKeysFromAddressIndex = async (
@@ -485,12 +497,12 @@ export const getKeysFromAddressIndex = async (
};
export const isAccountDeployedCairo0 = async (network: Network, publicKey: string) => {
- const { address } = getAccContractAddressAndCallDataCairo0(network.accountClassHash, publicKey);
+ const { address } = getAccContractAddressAndCallDataCairo0(publicKey);
return isAccountAddressDeployed(network, address, 0);
};
export const isAccountDeployed = async (network: Network, publicKey: string) => {
- const { address } = getAccContractAddressAndCallData(network.accountClassHash, publicKey);
+ const { address } = getAccContractAddressAndCallData(publicKey);
return isAccountAddressDeployed(network, address, 1);
};
@@ -540,6 +552,29 @@ export const validateAndParseAddress = (address: num.BigNumberish, length = 63)
return _validateAndParseAddressFn(address);
};
+export const findAddressIndex = async (
+ chainId: string,
+ address: string,
+ keyDeriver,
+ state: SnapState,
+ maxScan = 20,
+) => {
+ const bigIntAddress = num.toBigInt(address);
+ for (let i = 0; i < maxScan; i++) {
+ const { publicKey } = await getKeysFromAddressIndex(keyDeriver, chainId, state, i);
+ const { address: calculatedAddress } = getAccContractAddressAndCallData(publicKey);
+ const { address: calculatedAddressCairo0 } = getAccContractAddressAndCallDataCairo0(publicKey);
+ if (num.toBigInt(calculatedAddress) === bigIntAddress || num.toBigInt(calculatedAddressCairo0) === bigIntAddress) {
+ logger.log(`findAddressIndex:\nFound address in scan: ${i} ${address}`);
+ return {
+ index: i,
+ cairoVersion: num.toBigInt(calculatedAddress) === bigIntAddress ? 1 : 0,
+ };
+ }
+ }
+ throw new Error(`Address not found: ${address}`);
+};
+
export const isUpgradeRequired = async (network: Network, address: string) => {
try {
logger.log(`isUpgradeRequired: address = ${address}`);
@@ -550,16 +585,14 @@ export const isUpgradeRequired = async (network: Network, address: string) => {
if (!err.message.includes('Contract not found')) {
throw err;
}
+ //[TODO] if address is cario0 but not deployed we should throw error
return false;
}
};
export const getCorrectContractAddress = async (network: Network, publicKey: string) => {
- const { address: contractAddress } = getAccContractAddressAndCallData(network.accountClassHash, publicKey);
- const { address: contractAddressCairo0 } = getAccContractAddressAndCallDataCairo0(
- network.accountClassHashV0,
- publicKey,
- );
+ const { address: contractAddress } = getAccContractAddressAndCallData(publicKey);
+ const { address: contractAddressCairo0 } = getAccContractAddressAndCallDataCairo0(publicKey);
let pk = '';
logger.log(
`getContractAddressByKey: contractAddressCario1 = ${contractAddress}\ncontractAddressCairo0 = ${contractAddressCairo0}\npublicKey = ${publicKey}`,
@@ -591,3 +624,42 @@ export const getCorrectContractAddress = async (network: Network, publicKey: str
signerPubKey: pk,
};
};
+
+export const signTransactions = async (
+ privateKey: string,
+ transactions: Call[],
+ transactionsDetail: InvocationsSignerDetails,
+ abis: Abi[],
+): Promise => {
+ const signer = new Signer(privateKey);
+ const signatures = await signer.signTransaction(transactions, transactionsDetail, abis);
+ return stark.signatureToDecimalArray(signatures);
+};
+
+export const signDeployAccountTransaction = async (
+ privateKey: string,
+ transaction: DeployAccountSignerDetails,
+): Promise => {
+ const signer = new Signer(privateKey);
+ const signatures = await signer.signDeployAccountTransaction(transaction);
+ return stark.signatureToDecimalArray(signatures);
+};
+
+export const signDeclareTransaction = async (
+ privateKey: string,
+ transaction: DeclareSignerDetails,
+): Promise => {
+ const signer = new Signer(privateKey);
+ const signatures = await signer.signDeclareTransaction(transaction);
+ return stark.signatureToDecimalArray(signatures);
+};
+
+export const signMessage = async (
+ privateKey: Hex,
+ typedDataMessage: typedData.TypedData,
+ signerUserAddress: string,
+) => {
+ const signer = new Signer(privateKey);
+ const signatures = await signer.signMessage(typedDataMessage, signerUserAddress);
+ return stark.signatureToDecimalArray(signatures);
+};
diff --git a/packages/starknet-snap/src/utils/transaction/filter.ts b/packages/starknet-snap/src/utils/transaction/filter.ts
index 677e2f09..df16d33c 100644
--- a/packages/starknet-snap/src/utils/transaction/filter.ts
+++ b/packages/starknet-snap/src/utils/transaction/filter.ts
@@ -106,12 +106,12 @@ export class StatusFilter implements ITransactionFilter {
}
export class ChainIdFilter implements ITransactionFilter {
- chainId: number | undefined;
- constructor(chainId: number | undefined) {
+ chainId: string | undefined;
+ constructor(chainId: string | undefined) {
this.chainId = chainId;
}
apply(txn: Transaction): boolean {
- if (this.chainId) return Number(txn.chainId) === Number(this.chainId);
+ if (this.chainId) return num.toBigInt(txn.chainId) === num.toBigInt(this.chainId);
return true;
}
diff --git a/packages/starknet-snap/test/constants.test.ts b/packages/starknet-snap/test/constants.test.ts
index 9b02520b..b5d6c68c 100644
--- a/packages/starknet-snap/test/constants.test.ts
+++ b/packages/starknet-snap/test/constants.test.ts
@@ -61,6 +61,16 @@ export const account4: AccContract = {
chainId: constants.StarknetChainId.SN_GOERLI,
};
+export const Cario1Account1: AccContract = {
+ address: '0x043e3d703b005b8367a9783fb680713349c519202aa01e9beb170bdf710ae20b',
+ addressSalt: '0x019e59f349e1aa813ab4556c5836d0472e5e1ae82d1e5c3b3e8aabfeb290befd',
+ addressIndex: 1,
+ derivationPath: "m / bip32:44' / bip32:9004' / bip32:0' / bip32:0",
+ deployTxnHash: '0x5bc00132b8f2fc0f673dc232594b26727e712b204a2716f9dc28a8c5f607b5e',
+ publicKey: '0x019e59f349e1aa813ab4556c5836d0472e5e1ae82d1e5c3b3e8aabfeb290befd',
+ chainId: constants.StarknetChainId.SN_GOERLI,
+};
+
export const token1: Erc20Token = {
address: '0x244c20d51109adcf604fde1bbf878e5dcd549b3877ac87911ec6a158bd7aa62',
name: 'Starknet ERC-20 sample',
@@ -90,6 +100,23 @@ export const signature1 =
export const signature2 =
'30440220052956ac852275b6004c4e8042450f6dce83059f068029b037cc47338c80d062022002bc0e712f03e341bb3532fc356b779d84fcb4dbfe8ed34de2db66e121971d92';
+export const signature4Cario1SignMessage = [
+ '2941323345698930086258187297320132789256148405011604592758945785805412997864',
+ '1024747634926675542679366527128384456926978174336360356924884281219915547518',
+];
+export const signature4SignMessage = [
+ '784041227270069705374122994163964526105670242785431143890307285886848872447',
+ '2211270729821731368290303126976610283184761443640531855459727543936510195980',
+];
+export const signature4SignMessageWithUnfoundAddress = [
+ '2334603173889607172621639019166048758876763440301330097513705152117706117218',
+ '1236892621218974511001789530309582149943950152899985052022949903736308702610',
+];
+
+export const signature3 = [
+ '607985888254383597713678062496326274484078117880260232069103402822721981909',
+ '2165861203006010568296813740808310355035386348183576985427784501900302491063',
+];
// Derived from seed phrase: "dog simple gown ankle release anger local pulp rose river approve miracle"
export const bip44Entropy: JsonBIP44CoinTypeNode = {
depth: 2,
@@ -308,6 +335,20 @@ export const txn5: Transaction = {
eventIds: [],
};
+export const mainnetTxn1: Transaction = {
+ chainId: STARKNET_MAINNET_NETWORK.chainId,
+ contractAddress: '0x07394cbe418daa16e42b87ba67372d4ab4a5df0b05c6e554d158458ce245bc10',
+ contractCallData: ['0x0256d8f49882cc9366037415f48fa9fd2b5b7344ded7573ebfcef7c90e3e6b75', '2000000000000000000', '0'],
+ contractFuncName: 'transfer',
+ senderAddress: '0x05a98ec74a40383cf99896bfea2ec5e6aad16c7eed50025a5f569d585ebb13a2',
+ timestamp: 1653569160,
+ txnHash: '0x75ff16a2fd6b489d2e17673addba34af372907b0b23ff9068a23afa49c61999',
+ txnType: VoyagerTransactionType.INVOKE,
+ failureReason: '',
+ status: 'PENDING',
+ eventIds: [],
+};
+
export const getBalanceResp = {
result: ['0x0', '0x0'],
};
diff --git a/packages/starknet-snap/test/src/addNetwork.test.ts b/packages/starknet-snap/test/src/addNetwork.test.ts
index 1f678846..64e83b53 100644
--- a/packages/starknet-snap/test/src/addNetwork.test.ts
+++ b/packages/starknet-snap/test/src/addNetwork.test.ts
@@ -26,9 +26,13 @@ describe('Test function: addNetwork', function () {
wallet: walletStub,
saveMutex: new Mutex(),
};
-
+ let stateStub: sinon.SinonStub;
+ let dialogStub: sinon.SinonStub;
beforeEach(function () {
- walletStub.rpcStubs.snap_manageState.resolves(state);
+ stateStub = walletStub.rpcStubs.snap_manageState;
+ dialogStub = walletStub.rpcStubs.snap_dialog;
+ stateStub.resolves(state);
+ dialogStub.resolves(true);
});
afterEach(function () {
@@ -36,68 +40,60 @@ describe('Test function: addNetwork', function () {
sandbox.restore();
});
- it('should add the network correctly (should throw error as temporarily disabled)', async function () {
+ it('should add the network correctly', async function () {
const requestObject: AddNetworkRequestParams = {
networkName: 'Starknet Unit SN_GOERLI',
networkChainId: '0x534e5f474f777',
networkBaseUrl: 'https://alpha-unit-SN_GOERLI.starknet.io',
- networkNodeUrl: '',
+ networkNodeUrl: 'https://alpha-unit-SN_GOERLI.starknet.io',
};
apiParams.requestParams = requestObject;
- try {
- await addNetwork(apiParams);
- return;
- } catch (err) {
- expect(err).to.be.an('Error');
- expect(err.message).to.be.eql('addNetwork is currently disabled');
- }
+ const result = await addNetwork(apiParams);
+ expect(result).to.be.eql(true);
+ expect(stateStub).to.be.calledOnce;
+ expect(state.networks.length).to.be.eql(3);
});
- it('should update the network correctly (should throw error as temporarily disabled)', async function () {
+ it('should update the network correctly', async function () {
const requestObject: AddNetworkRequestParams = {
networkName: 'Starknet Unit SN_GOERLI 2',
networkChainId: '0x534e5f474f777',
networkBaseUrl: 'https://alpha-unit-SN_GOERLI-2.starknet.io',
- networkNodeUrl: '',
+ networkNodeUrl: 'https://alpha-unit-SN_GOERLI.starknet.io',
};
apiParams.requestParams = requestObject;
- try {
- await addNetwork(apiParams);
- } catch (err) {
- expect(err).to.be.an('Error');
- expect(err.message).to.be.eql('addNetwork is currently disabled');
- }
+ const result = await addNetwork(apiParams);
+ expect(result).to.be.eql(true);
+ expect(stateStub).to.be.calledOnce;
+ expect(state.networks.length).to.be.eql(3);
});
- it('should not update snap state with the duplicated network (should throw error as temporarily disabled)', async function () {
+ it('should not update snap state with the duplicated network', async function () {
const requestObject: AddNetworkRequestParams = {
networkName: 'Starknet Unit SN_GOERLI 2',
networkChainId: '0x534e5f474f777',
networkBaseUrl: 'https://alpha-unit-SN_GOERLI-2.starknet.io',
- networkNodeUrl: '',
+ networkNodeUrl: 'https://alpha-unit-SN_GOERLI.starknet.io',
};
apiParams.requestParams = requestObject;
- try {
- await addNetwork(apiParams);
- } catch (err) {
- expect(err).to.be.an('Error');
- expect(err.message).to.be.eql('addNetwork is currently disabled');
- }
+ const result = await addNetwork(apiParams);
+ expect(result).to.be.eql(true);
+ expect(stateStub).to.be.callCount(0);
+ expect(state.networks.length).to.be.eql(3);
});
- it('should throw error if upsertNetwork failed', async function () {
+ it('should throw an error if upsertNetwork failed', async function () {
sandbox.stub(snapUtils, 'upsertNetwork').throws(new Error());
const requestObject: AddNetworkRequestParams = {
networkName: 'Starknet Unit SN_GOERLI 2',
networkChainId: '0x534e5f474f777',
networkBaseUrl: 'https://alpha-unit-SN_GOERLI-2.starknet.io',
- networkNodeUrl: '',
+ networkNodeUrl: 'https://alpha-unit-SN_GOERLI.starknet.io',
};
apiParams.requestParams = requestObject;
-
let result;
try {
- await addNetwork(apiParams);
+ result = await addNetwork(apiParams);
} catch (err) {
result = err;
} finally {
@@ -286,34 +282,12 @@ describe('Test function: addNetwork', function () {
}
});
- it('should throw an error if the network account class hash is not valid', async function () {
- const requestObject: AddNetworkRequestParams = {
- networkName: 'Starknet Unit SN_GOERLI',
- networkChainId: '0x534e5f474f777',
- networkBaseUrl: '',
- networkNodeUrl: 'http://alpha-unit-SN_GOERLI-2.starknet.io',
- accountClassHash: '0x811111111111111111111111111111111111111111111111111111111111111',
- // a valid Starknet hash is essentially a cario felt, which is a 251 bit positive number
- // which means it can only be 63 hex character long with the leading char being [1-7]
- };
- apiParams.requestParams = requestObject;
- let result;
- try {
- result = await addNetwork(apiParams);
- } catch (err) {
- result = err;
- } finally {
- expect(result).to.be.an('Error');
- }
- });
-
it('should throw an error if the network chainId is one of the preloaded network chainId', async function () {
const requestObject: AddNetworkRequestParams = {
networkName: 'Starknet Unit SN_GOERLI',
networkChainId: '0x534e5f474f45524c49',
networkBaseUrl: 'http://alpha-unit-SN_GOERLI-2.starknet.io',
networkNodeUrl: '',
- accountClassHash: '0x3e327de1c40540b98d05cbcb13552008e36f0ec8d61d46956d2f9752c294328',
};
apiParams.requestParams = requestObject;
let result;
@@ -328,11 +302,10 @@ describe('Test function: addNetwork', function () {
it('should throw an error if the network name is one of the preloaded network name', async function () {
const requestObject: AddNetworkRequestParams = {
- networkName: 'Goerli SN_GOERLI',
- networkChainId: '0x12345678',
- networkBaseUrl: 'http://alpha-unit-SN_GOERLI-2.starknet.io',
- networkNodeUrl: '',
- accountClassHash: '0x3e327de1c40540b98d05cbcb13552008e36f0ec8d61d46956d2f9752c294328',
+ networkName: STARKNET_TESTNET_NETWORK.name,
+ networkChainId: STARKNET_TESTNET_NETWORK.chainId,
+ networkBaseUrl: STARKNET_TESTNET_NETWORK.baseUrl,
+ networkNodeUrl: STARKNET_TESTNET_NETWORK.nodeUrl,
};
apiParams.requestParams = requestObject;
let result;
diff --git a/packages/starknet-snap/test/src/createAccount.test.ts b/packages/starknet-snap/test/src/createAccount.test.ts
index 88a9de7b..2b9a8936 100644
--- a/packages/starknet-snap/test/src/createAccount.test.ts
+++ b/packages/starknet-snap/test/src/createAccount.test.ts
@@ -75,10 +75,7 @@ describe('Test function: createAccount', function () {
state,
-1,
);
- const { address: contractAddress } = utils.getAccContractAddressAndCallData(
- STARKNET_MAINNET_NETWORK.accountClassHash,
- publicKey,
- );
+ const { address: contractAddress } = utils.getAccContractAddressAndCallData(publicKey);
expect(walletStub.rpcStubs.snap_manageState).to.have.been.callCount(0);
expect(result.address).to.be.eq(contractAddress);
expect(state.accContracts.length).to.be.eq(0);
@@ -292,6 +289,8 @@ describe('Test function: createAccount', function () {
return createAccountFailedProxyResp;
});
sandbox.stub(utils, 'isAccountAddressDeployed').resolves(false);
+ sandbox.stub(utils, 'callContract').resolves(getBalanceResp);
+ sandbox.stub(utils, 'getSigner').throws(new Error());
sandbox.stub(utils, 'estimateAccountDeployFee').callsFake(async () => {
return estimateDeployFeeResp;
});
@@ -311,6 +310,8 @@ describe('Test function: createAccount', function () {
return createAccountProxyResp;
});
sandbox.stub(utils, 'isAccountAddressDeployed').resolves(false);
+ sandbox.stub(utils, 'callContract').resolves(getBalanceResp);
+ sandbox.stub(utils, 'getSigner').throws(new Error());
sandbox.stub(utils, 'estimateAccountDeployFee').callsFake(async () => {
return estimateDeployFeeResp;
});
diff --git a/packages/starknet-snap/test/src/declareContract.test.ts b/packages/starknet-snap/test/src/declareContract.test.ts
new file mode 100644
index 00000000..30f1616a
--- /dev/null
+++ b/packages/starknet-snap/test/src/declareContract.test.ts
@@ -0,0 +1,121 @@
+import chai, { expect } from 'chai';
+import sinon from 'sinon';
+import sinonChai from 'sinon-chai';
+import { WalletMock } from '../wallet.mock.test';
+import * as utils from '../../src/utils/starknetUtils';
+import { declareContract } from '../../src/declareContract';
+import { SnapState } from '../../src/types/snapState';
+import { STARKNET_MAINNET_NETWORK, STARKNET_TESTNET_NETWORK } from '../../src/utils/constants';
+import { createAccountProxyTxn, getBip44EntropyStub, account1 } from '../constants.test';
+import { getAddressKeyDeriver } from '../../src/utils/keyPair';
+import { Mutex } from 'async-mutex';
+import { ApiParams, DeclareContractRequestParams } from '../../src/types/snapApi';
+
+chai.use(sinonChai);
+const sandbox = sinon.createSandbox();
+
+describe('Test function: declareContract', function () {
+ this.timeout(10000);
+ const walletStub = new WalletMock();
+ const state: SnapState = {
+ accContracts: [account1],
+ erc20Tokens: [],
+ networks: [STARKNET_MAINNET_NETWORK, STARKNET_TESTNET_NETWORK],
+ transactions: [],
+ };
+ const apiParams: ApiParams = {
+ state,
+ requestParams: {},
+ wallet: walletStub,
+ saveMutex: new Mutex(),
+ };
+
+ const requestObject: DeclareContractRequestParams = {
+ chainId: STARKNET_TESTNET_NETWORK.chainId,
+ senderAddress: account1.address,
+ contractPayload: {
+ contract: 'TestContract',
+ },
+ invocationsDetails: {
+ maxFee: 100,
+ },
+ };
+
+ beforeEach(async function () {
+ walletStub.rpcStubs.snap_getBip44Entropy.callsFake(getBip44EntropyStub);
+ apiParams.keyDeriver = await getAddressKeyDeriver(walletStub);
+ apiParams.requestParams = requestObject;
+ sandbox.useFakeTimers(createAccountProxyTxn.timestamp);
+ walletStub.rpcStubs.snap_dialog.resolves(true);
+ walletStub.rpcStubs.snap_manageState.resolves(state);
+ });
+
+ afterEach(function () {
+ walletStub.reset();
+ sandbox.restore();
+ });
+
+ it('should declareContract correctly', async function () {
+ const declareContractStub = sandbox.stub(utils, 'declareContract').resolves({
+ transaction_hash: 'transaction_hash',
+ class_hash: 'class_hash',
+ });
+ const result = await declareContract(apiParams);
+ const { privateKey } = await utils.getKeysFromAddress(
+ apiParams.keyDeriver,
+ STARKNET_TESTNET_NETWORK,
+ state,
+ account1.address,
+ );
+
+ expect(result).to.eql({
+ transaction_hash: 'transaction_hash',
+ class_hash: 'class_hash',
+ });
+ expect(declareContractStub).to.have.been.calledOnce;
+ expect(declareContractStub).to.have.been.calledWith(
+ STARKNET_TESTNET_NETWORK,
+ account1.address,
+ privateKey,
+ { contract: 'TestContract' },
+ { maxFee: 100 },
+ );
+ });
+
+ it('should throw error if declareContract fail', async function () {
+ const declareContractStub = sandbox.stub(utils, 'declareContract').rejects('error');
+ const { privateKey } = await utils.getKeysFromAddress(
+ apiParams.keyDeriver,
+ STARKNET_TESTNET_NETWORK,
+ state,
+ account1.address,
+ );
+ let result;
+ try {
+ await declareContract(apiParams);
+ } catch (e) {
+ result = e;
+ } finally {
+ expect(result).to.be.an('Error');
+ expect(declareContractStub).to.have.been.calledOnce;
+ expect(declareContractStub).to.have.been.calledWith(
+ STARKNET_TESTNET_NETWORK,
+ account1.address,
+ privateKey,
+ { contract: 'TestContract' },
+ { maxFee: 100 },
+ );
+ }
+ });
+
+ it('should return false if user rejected to sign the transaction', async function () {
+ walletStub.rpcStubs.snap_dialog.resolves(false);
+ const declareContractStub = sandbox.stub(utils, 'declareContract').resolves({
+ transaction_hash: 'transaction_hash',
+ class_hash: 'class_hash',
+ });
+ const result = await declareContract(apiParams);
+ expect(result).to.equal(false);
+ expect(declareContractStub).to.have.been.not.called;
+ });
+});
diff --git a/packages/starknet-snap/test/src/estimateFee.test.ts b/packages/starknet-snap/test/src/estimateFee.test.ts
index 09cc27fe..8be863b6 100644
--- a/packages/starknet-snap/test/src/estimateFee.test.ts
+++ b/packages/starknet-snap/test/src/estimateFee.test.ts
@@ -5,11 +5,19 @@ import { WalletMock } from '../wallet.mock.test';
import * as utils from '../../src/utils/starknetUtils';
import { estimateFee } from '../../src/estimateFee';
import { SnapState } from '../../src/types/snapState';
-import { STARKNET_TESTNET_NETWORK } from '../../src/utils/constants';
+import { ACCOUNT_CLASS_HASH_V1, STARKNET_TESTNET_NETWORK } from '../../src/utils/constants';
import { getAddressKeyDeriver } from '../../src/utils/keyPair';
-import { account2, estimateDeployFeeResp4, estimateFeeResp, getBip44EntropyStub } from '../constants.test';
+import {
+ account2,
+ Cario1Account1,
+ estimateDeployFeeResp4,
+ estimateFeeResp,
+ getBip44EntropyStub,
+ getBalanceResp,
+} from '../constants.test';
import { Mutex } from 'async-mutex';
import { ApiParams, EstimateFeeRequestParams } from '../../src/types/snapApi';
+import { TransactionType } from 'starknet';
chai.use(sinonChai);
const sandbox = sinon.createSandbox();
@@ -18,7 +26,7 @@ describe('Test function: estimateFee', function () {
const walletStub = new WalletMock();
const state: SnapState = {
- accContracts: [account2],
+ accContracts: [],
erc20Tokens: [],
networks: [STARKNET_TESTNET_NETWORK],
transactions: [],
@@ -39,6 +47,7 @@ describe('Test function: estimateFee', function () {
beforeEach(async function () {
walletStub.rpcStubs.snap_getBip44Entropy.callsFake(getBip44EntropyStub);
apiParams.keyDeriver = await getAddressKeyDeriver(walletStub);
+ sandbox.stub(utils, 'callContract').resolves(getBalanceResp);
});
afterEach(function () {
@@ -129,69 +138,133 @@ describe('Test function: estimateFee', function () {
sandbox.stub(utils, 'isUpgradeRequired').resolves(false);
});
- describe('when account is deployed', function () {
+ describe('when account is cario1 address', function () {
beforeEach(async function () {
- estimateFeeBulkStub = sandbox.stub(utils, 'estimateFeeBulk');
- sandbox.stub(utils, 'isAccountDeployed').resolves(true);
+ apiParams.requestParams = {
+ ...apiParams.requestParams,
+ senderAddress: Cario1Account1.address,
+ };
});
- it('should estimate the fee correctly', async function () {
- estimateFeeStub = sandbox.stub(utils, 'estimateFee').resolves(estimateFeeResp);
+ describe('when account is deployed', function () {
+ beforeEach(async function () {
+ estimateFeeBulkStub = sandbox.stub(utils, 'estimateFeeBulk');
+ sandbox.stub(utils, 'isAccountDeployed').resolves(true);
+ });
- const result = await estimateFee(apiParams);
- expect(result.suggestedMaxFee).to.be.eq(estimateFeeResp.suggestedMaxFee.toString(10));
- expect(estimateFeeStub).callCount(1);
- expect(estimateFeeBulkStub).callCount(0);
- });
-
- it('should throw error if estimateFee failed', async function () {
- estimateFeeStub = sandbox.stub(utils, 'estimateFee').throws('Error');
- apiParams.requestParams = requestObject;
-
- let result;
- try {
- await estimateFee(apiParams);
- } catch (err) {
- result = err;
- } finally {
- expect(result).to.be.an('Error');
+ it('should estimate the fee correctly', async function () {
+ estimateFeeStub = sandbox.stub(utils, 'estimateFee').resolves(estimateFeeResp);
+ const result = await estimateFee(apiParams);
+ expect(result.suggestedMaxFee).to.be.eq(estimateFeeResp.suggestedMaxFee.toString(10));
expect(estimateFeeStub).callCount(1);
expect(estimateFeeBulkStub).callCount(0);
- }
+ });
});
- });
- describe('when account is not deployed', function () {
- beforeEach(async function () {
- estimateFeeStub = sandbox.stub(utils, 'estimateFee');
- sandbox.stub(utils, 'isAccountDeployed').resolves(false);
- });
+ describe('when account is not deployed', function () {
+ beforeEach(async function () {
+ estimateFeeStub = sandbox.stub(utils, 'estimateFee');
+ sandbox.stub(utils, 'isAccountDeployed').resolves(false);
+ });
- it('should estimate the fee including deploy txn correctly', async function () {
- estimateFeeBulkStub = sandbox
- .stub(utils, 'estimateFeeBulk')
- .resolves([estimateFeeResp, estimateDeployFeeResp4]);
- const expectedSuggestedMaxFee = estimateDeployFeeResp4.suggestedMaxFee + estimateFeeResp.suggestedMaxFee;
- const result = await estimateFee(apiParams);
- expect(result.suggestedMaxFee).to.be.eq(expectedSuggestedMaxFee.toString(10));
- expect(estimateFeeStub).callCount(0);
- expect(estimateFeeBulkStub).callCount(1);
- });
+ it('should estimate the fee including deploy txn correctly', async function () {
+ estimateFeeBulkStub = sandbox
+ .stub(utils, 'estimateFeeBulk')
+ .resolves([estimateFeeResp, estimateDeployFeeResp4]);
+ const expectedSuggestedMaxFee = estimateDeployFeeResp4.suggestedMaxFee + estimateFeeResp.suggestedMaxFee;
+ const result = await estimateFee(apiParams);
+
+ const { privateKey, publicKey } = await utils.getKeysFromAddress(
+ apiParams.keyDeriver,
+ STARKNET_TESTNET_NETWORK,
+ state,
+ Cario1Account1.address,
+ );
+ const { callData } = utils.getAccContractAddressAndCallData(publicKey);
+ const apiRequest = apiParams.requestParams as EstimateFeeRequestParams;
+
+ const expectedBulkTransaction = [
+ {
+ type: TransactionType.DEPLOY_ACCOUNT,
+ payload: {
+ classHash: ACCOUNT_CLASS_HASH_V1,
+ contractAddress: Cario1Account1.address,
+ constructorCalldata: callData,
+ addressSalt: publicKey,
+ },
+ },
+ {
+ type: TransactionType.INVOKE,
+ payload: {
+ contractAddress: apiRequest.contractAddress,
+ entrypoint: apiRequest.contractFuncName,
+ calldata: utils.getCallDataArray(apiRequest.contractCallData),
+ },
+ },
+ ];
- it('should throw error if estimateFee failed', async function () {
- estimateFeeBulkStub = sandbox.stub(utils, 'estimateFeeBulk').throws('Error');
- apiParams.requestParams = requestObject;
-
- let result;
- try {
- await estimateFee(apiParams);
- } catch (err) {
- result = err;
- } finally {
- expect(result).to.be.an('Error');
+ expect(result.suggestedMaxFee).to.be.eq(expectedSuggestedMaxFee.toString(10));
expect(estimateFeeStub).callCount(0);
expect(estimateFeeBulkStub).callCount(1);
- }
+ expect(estimateFeeBulkStub).to.be.calledWith(
+ STARKNET_TESTNET_NETWORK,
+ Cario1Account1.address,
+ privateKey,
+ expectedBulkTransaction,
+ );
+ });
+
+ it('should throw error if estimateFee failed', async function () {
+ estimateFeeBulkStub = sandbox.stub(utils, 'estimateFeeBulk').throws('Error');
+ apiParams.requestParams = requestObject;
+
+ let result;
+ try {
+ await estimateFee(apiParams);
+ } catch (err) {
+ result = err;
+ } finally {
+ expect(result).to.be.an('Error');
+ expect(estimateFeeStub).callCount(0);
+ expect(estimateFeeBulkStub).callCount(1);
+ }
+ });
+ });
+ });
+
+ describe('when account is cario0 address', function () {
+ describe('when account is deployed', function () {
+ beforeEach(async function () {
+ estimateFeeBulkStub = sandbox.stub(utils, 'estimateFeeBulk');
+ sandbox.stub(utils, 'isAccountDeployed').resolves(true);
+ });
+
+ it('should estimate the fee correctly', async function () {
+ estimateFeeStub = sandbox.stub(utils, 'estimateFee').resolves(estimateFeeResp);
+ const result = await estimateFee(apiParams);
+ expect(result.suggestedMaxFee).to.be.eq(estimateFeeResp.suggestedMaxFee.toString(10));
+ expect(estimateFeeStub).callCount(1);
+ expect(estimateFeeBulkStub).callCount(0);
+ });
+
+ it('should throw error if estimateFee failed', async function () {
+ estimateFeeStub = sandbox.stub(utils, 'estimateFee').throws('Error');
+ apiParams.requestParams = requestObject;
+
+ let result;
+ try {
+ await estimateFee(apiParams);
+ } catch (err) {
+ result = err;
+ } finally {
+ expect(result).to.be.an('Error');
+ expect(estimateFeeStub).callCount(1);
+ expect(estimateFeeBulkStub).callCount(0);
+ }
+ });
+ });
+ describe('when account is not deployed', function () {
+ //not support cario0 address if not deployed
});
});
});
diff --git a/packages/starknet-snap/test/src/estimateFees.test.ts b/packages/starknet-snap/test/src/estimateFees.test.ts
new file mode 100644
index 00000000..5e004d03
--- /dev/null
+++ b/packages/starknet-snap/test/src/estimateFees.test.ts
@@ -0,0 +1,101 @@
+import chai, { expect } from 'chai';
+import sinon from 'sinon';
+import sinonChai from 'sinon-chai';
+import { WalletMock } from '../wallet.mock.test';
+import { SnapState } from '../../src/types/snapState';
+import { estimateFees } from '../../src/estimateFees';
+import { STARKNET_TESTNET_NETWORK } from '../../src/utils/constants';
+import { account2, estimateDeployFeeResp2, estimateDeployFeeResp3, getBip44EntropyStub } from '../constants.test';
+import { getAddressKeyDeriver } from '../../src/utils/keyPair';
+import * as utils from '../../src/utils/starknetUtils';
+import { Mutex } from 'async-mutex';
+import { ApiParams } from '../../src/types/snapApi';
+import { TransactionType } from 'starknet';
+chai.use(sinonChai);
+const sandbox = sinon.createSandbox();
+
+describe('Test function: estimateFees', function () {
+ this.timeout(5000);
+ const walletStub = new WalletMock();
+ const state: SnapState = {
+ accContracts: [account2],
+ erc20Tokens: [],
+ networks: [STARKNET_TESTNET_NETWORK],
+ transactions: [],
+ };
+ const apiParams: ApiParams = {
+ state,
+ requestParams: {},
+ wallet: walletStub,
+ saveMutex: new Mutex(),
+ };
+
+ beforeEach(async function () {
+ walletStub.rpcStubs.snap_getBip44Entropy.callsFake(getBip44EntropyStub);
+ apiParams.keyDeriver = await getAddressKeyDeriver(walletStub);
+ });
+
+ afterEach(function () {
+ walletStub.reset();
+ sandbox.restore();
+ });
+
+ it('should estimate the fee including deploy txn correctly', async function () {
+ const feeResult = [estimateDeployFeeResp2, estimateDeployFeeResp3];
+ sandbox.stub(utils, 'estimateFeeBulk').callsFake(async () => {
+ return feeResult;
+ });
+ apiParams.requestParams = {
+ senderAddress: account2.address,
+ chainId: STARKNET_TESTNET_NETWORK.chainId,
+ invocations: [
+ {
+ type: TransactionType.INVOKE,
+ payload: {
+ entrypoint: 'transfer',
+ contractAddress: '0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
+ calldata: ['1697416752243704114657612983658108968471303240361660550219082009242042413588', '1', '0'],
+ },
+ },
+ ],
+ };
+ const expectedResult = feeResult.map((fee) => ({
+ overall_fee: fee.overall_fee.toString(10) || '0',
+ gas_consumed: fee.gas_consumed.toString(10) || '0',
+ gas_price: fee.gas_price.toString(10) || '0',
+ suggestedMaxFee: fee.suggestedMaxFee.toString(10) || '0',
+ }));
+ const result = await estimateFees(apiParams);
+ expect(result).to.eql(expectedResult);
+ });
+
+ it('should throw error if estimateFee failed', async function () {
+ sandbox.stub(utils, 'getSigner').callsFake(async () => {
+ return account2.publicKey;
+ });
+ sandbox.stub(utils, 'estimateFeeBulk').throws(new Error());
+ apiParams.requestParams = {
+ senderAddress: account2.address,
+ chainId: STARKNET_TESTNET_NETWORK.chainId,
+ invocations: [
+ {
+ type: TransactionType.INVOKE,
+ payload: {
+ entrypoint: 'transfer',
+ contractAddress: '0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
+ calldata: ['1697416752243704114657612983658108968471303240361660550219082009242042413588', '1', '0'],
+ },
+ },
+ ],
+ };
+
+ let result;
+ try {
+ await estimateFees(apiParams);
+ } catch (err) {
+ result = err;
+ } finally {
+ expect(result).to.be.an('Error');
+ }
+ });
+});
diff --git a/packages/starknet-snap/test/src/executeTxn.test.ts b/packages/starknet-snap/test/src/executeTxn.test.ts
new file mode 100644
index 00000000..036fd045
--- /dev/null
+++ b/packages/starknet-snap/test/src/executeTxn.test.ts
@@ -0,0 +1,187 @@
+import chai, { expect } from 'chai';
+import sinon from 'sinon';
+import sinonChai from 'sinon-chai';
+import { WalletMock } from '../wallet.mock.test';
+import * as utils from '../../src/utils/starknetUtils';
+import { executeTxn } from '../../src/executeTxn';
+import { SnapState } from '../../src/types/snapState';
+import { STARKNET_MAINNET_NETWORK, STARKNET_TESTNET_NETWORK } from '../../src/utils/constants';
+import { createAccountProxyTxn, getBip44EntropyStub, account1 } from '../constants.test';
+import { getAddressKeyDeriver } from '../../src/utils/keyPair';
+import { Mutex } from 'async-mutex';
+import { ApiParams, ExecuteTxnRequestParams } from '../../src/types/snapApi';
+
+chai.use(sinonChai);
+const sandbox = sinon.createSandbox();
+
+describe('Test function: executeTxn', function () {
+ this.timeout(10000);
+ const walletStub = new WalletMock();
+ const state: SnapState = {
+ accContracts: [],
+ erc20Tokens: [],
+ networks: [STARKNET_MAINNET_NETWORK, STARKNET_TESTNET_NETWORK],
+ transactions: [],
+ };
+ const apiParams: ApiParams = {
+ state,
+ requestParams: {},
+ wallet: walletStub,
+ saveMutex: new Mutex(),
+ };
+
+ const requestObject: ExecuteTxnRequestParams = {
+ chainId: STARKNET_MAINNET_NETWORK.chainId,
+ senderAddress: account1.address,
+ txnInvocation: {
+ entrypoint: 'transfer',
+ calldata: ['0', '0', '0'],
+ contractAddress: createAccountProxyTxn.contractAddress,
+ },
+ invocationsDetails: {
+ maxFee: 100,
+ },
+ };
+
+ beforeEach(async function () {
+ walletStub.rpcStubs.snap_getBip44Entropy.callsFake(getBip44EntropyStub);
+ apiParams.keyDeriver = await getAddressKeyDeriver(walletStub);
+ apiParams.requestParams = requestObject;
+ sandbox.useFakeTimers(createAccountProxyTxn.timestamp);
+ walletStub.rpcStubs.snap_dialog.resolves(true);
+ walletStub.rpcStubs.snap_manageState.resolves(state);
+ });
+
+ afterEach(function () {
+ walletStub.reset();
+ sandbox.restore();
+ apiParams.requestParams = requestObject;
+ });
+
+ it('should executeTxn correctly', async function () {
+ const stub = sandbox.stub(utils, 'executeTxn').resolves({
+ transaction_hash: 'transaction_hash',
+ });
+ const result = await executeTxn(apiParams);
+ const { privateKey } = await utils.getKeysFromAddress(
+ apiParams.keyDeriver,
+ STARKNET_MAINNET_NETWORK,
+ state,
+ account1.address,
+ );
+
+ expect(result).to.eql({
+ transaction_hash: 'transaction_hash',
+ });
+ expect(stub).to.have.been.calledOnce;
+ expect(stub).to.have.been.calledWith(
+ STARKNET_MAINNET_NETWORK,
+ account1.address,
+ privateKey,
+ {
+ entrypoint: 'transfer',
+ calldata: ['0', '0', '0'],
+ contractAddress: createAccountProxyTxn.contractAddress,
+ },
+ undefined,
+ { maxFee: 100 },
+ );
+ });
+
+ it('should executeTxn multiple', async function () {
+ const stub = sandbox.stub(utils, 'executeTxn').resolves({
+ transaction_hash: 'transaction_hash',
+ });
+ apiParams.requestParams = {
+ chainId: STARKNET_MAINNET_NETWORK.chainId,
+ senderAddress: account1.address,
+ txnInvocation: [
+ {
+ entrypoint: 'transfer',
+ calldata: ['0', '0', '0'],
+ contractAddress: createAccountProxyTxn.contractAddress,
+ },
+ {
+ entrypoint: 'transfer2',
+ calldata: ['0', '0', '0'],
+ contractAddress: createAccountProxyTxn.contractAddress,
+ },
+ ],
+ invocationsDetails: {
+ maxFee: 100,
+ },
+ };
+ const result = await executeTxn(apiParams);
+ const { privateKey } = await utils.getKeysFromAddress(
+ apiParams.keyDeriver,
+ STARKNET_MAINNET_NETWORK,
+ state,
+ account1.address,
+ );
+
+ expect(result).to.eql({
+ transaction_hash: 'transaction_hash',
+ });
+ expect(stub).to.have.been.calledOnce;
+ expect(stub).to.have.been.calledWith(
+ STARKNET_MAINNET_NETWORK,
+ account1.address,
+ privateKey,
+ [
+ {
+ entrypoint: 'transfer',
+ calldata: ['0', '0', '0'],
+ contractAddress: createAccountProxyTxn.contractAddress,
+ },
+ {
+ entrypoint: 'transfer2',
+ calldata: ['0', '0', '0'],
+ contractAddress: createAccountProxyTxn.contractAddress,
+ },
+ ],
+ undefined,
+ { maxFee: 100 },
+ );
+ });
+
+ it('should throw error if executeTxn fail', async function () {
+ const stub = sandbox.stub(utils, 'executeTxn').rejects('error');
+ const { privateKey } = await utils.getKeysFromAddress(
+ apiParams.keyDeriver,
+ STARKNET_MAINNET_NETWORK,
+ state,
+ account1.address,
+ );
+ let result;
+ try {
+ await executeTxn(apiParams);
+ } catch (e) {
+ result = e;
+ } finally {
+ expect(result).to.be.an('Error');
+ expect(stub).to.have.been.calledOnce;
+ expect(stub).to.have.been.calledWith(
+ STARKNET_MAINNET_NETWORK,
+ account1.address,
+ privateKey,
+ {
+ entrypoint: 'transfer',
+ calldata: ['0', '0', '0'],
+ contractAddress: createAccountProxyTxn.contractAddress,
+ },
+ undefined,
+ { maxFee: 100 },
+ );
+ }
+ });
+
+ it('should return false if user rejected to sign the transaction', async function () {
+ walletStub.rpcStubs.snap_dialog.resolves(false);
+ const stub = sandbox.stub(utils, 'executeTxn').resolves({
+ transaction_hash: 'transaction_hash',
+ });
+ const result = await executeTxn(apiParams);
+ expect(result).to.equal(false);
+ expect(stub).to.have.been.not.called;
+ });
+});
diff --git a/packages/starknet-snap/test/src/getCurrentNetwork.test.ts b/packages/starknet-snap/test/src/getCurrentNetwork.test.ts
new file mode 100644
index 00000000..1b706305
--- /dev/null
+++ b/packages/starknet-snap/test/src/getCurrentNetwork.test.ts
@@ -0,0 +1,53 @@
+import chai, { expect } from 'chai';
+import sinon from 'sinon';
+import sinonChai from 'sinon-chai';
+import { WalletMock } from '../wallet.mock.test';
+import { SnapState } from '../../src/types/snapState';
+import { STARKNET_MAINNET_NETWORK, STARKNET_TESTNET_NETWORK } from '../../src/utils/constants';
+import { getCurrentNetwork } from '../../src/getCurrentNetwork';
+import { Mutex } from 'async-mutex';
+import { ApiParams } from '../../src/types/snapApi';
+
+chai.use(sinonChai);
+const sandbox = sinon.createSandbox();
+
+describe('Test function: getStoredNetworks', function () {
+ const walletStub = new WalletMock();
+ const state: SnapState = {
+ accContracts: [],
+ erc20Tokens: [],
+ networks: [STARKNET_TESTNET_NETWORK, STARKNET_MAINNET_NETWORK],
+ transactions: [],
+ currentNetwork: STARKNET_MAINNET_NETWORK,
+ };
+ const apiParams: ApiParams = {
+ state,
+ requestParams: {},
+ wallet: walletStub,
+ saveMutex: new Mutex(),
+ };
+
+ let stateStub: sinon.SinonStub;
+ beforeEach(function () {
+ stateStub = walletStub.rpcStubs.snap_manageState;
+ stateStub.resolves(state);
+ });
+
+ afterEach(function () {
+ walletStub.reset();
+ sandbox.restore();
+ });
+
+ it('should get the current network correctly', async function () {
+ const result = await getCurrentNetwork(apiParams);
+ expect(stateStub).not.to.have.been.called;
+ expect(result).to.be.eql(STARKNET_MAINNET_NETWORK);
+ });
+
+ it('should get STARKNET_TESTNET_NETWORK if current network is undefined', async function () {
+ state.currentNetwork = undefined;
+ const result = await getCurrentNetwork(apiParams);
+ expect(stateStub).not.to.have.been.called;
+ expect(result).to.be.eql(STARKNET_TESTNET_NETWORK);
+ });
+});
diff --git a/packages/starknet-snap/test/src/getTransactions.test.ts b/packages/starknet-snap/test/src/getTransactions.test.ts
index cc9fe024..938f706a 100644
--- a/packages/starknet-snap/test/src/getTransactions.test.ts
+++ b/packages/starknet-snap/test/src/getTransactions.test.ts
@@ -23,6 +23,7 @@ import {
txn3,
txn4,
txn5,
+ mainnetTxn1,
} from '../constants.test';
import { getTransactions, updateStatus } from '../../src/getTransactions';
import { Mutex } from 'async-mutex';
@@ -45,6 +46,7 @@ describe('Test function: getTransactions', function () {
{ ...txn3 },
{ ...txn4 },
{ ...txn5 },
+ { ...mainnetTxn1 },
{ ...createAccountProxyTxn },
{ ...initAccountTxn },
],
diff --git a/packages/starknet-snap/test/src/recoverAccounts.test.ts b/packages/starknet-snap/test/src/recoverAccounts.test.ts
index 36cc4ff9..27264081 100644
--- a/packages/starknet-snap/test/src/recoverAccounts.test.ts
+++ b/packages/starknet-snap/test/src/recoverAccounts.test.ts
@@ -283,24 +283,4 @@ describe('Test function: recoverAccounts', function () {
expect(result).to.be.an('Error');
}
});
-
- it('should show confirmation box with failure msg if network accountClassHash is missing', async function () {
- const maxScanned = 5;
- const maxMissed = 3;
- const getCorrectContractAddressStub = sandbox.stub(utils, 'getCorrectContractAddress');
- const isUpgradeRequiredStub = sandbox.stub(utils, 'isUpgradeRequired');
- getCorrectContractAddressStub.resolves({ address: mainnetAccAddresses[0], signerPubKey: mainnetPublicKeys[0] });
- isUpgradeRequiredStub.resolves(false);
-
- const requestObject: RecoverAccountsRequestParams = {
- startScanIndex: 0,
- maxScanned,
- maxMissed,
- chainId: INVALID_NETWORK.chainId,
- };
- apiParams.requestParams = requestObject;
- const result = await recoverAccounts(apiParams);
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
- expect(result).eql(null);
- });
});
diff --git a/packages/starknet-snap/test/src/sendTransaction.test.ts b/packages/starknet-snap/test/src/sendTransaction.test.ts
index 4610bb52..c1e5ee43 100644
--- a/packages/starknet-snap/test/src/sendTransaction.test.ts
+++ b/packages/starknet-snap/test/src/sendTransaction.test.ts
@@ -21,6 +21,7 @@ import {
token2,
token3,
unfoundUserAddress,
+ Cario1Account1,
} from '../constants.test';
import { getAddressKeyDeriver } from '../../src/utils/keyPair';
import { Mutex } from 'async-mutex';
@@ -34,7 +35,7 @@ describe('Test function: sendTransaction', function () {
this.timeout(5000);
const walletStub = new WalletMock();
const state: SnapState = {
- accContracts: [account1],
+ accContracts: [],
erc20Tokens: [token2, token3],
networks: [STARKNET_TESTNET_NETWORK],
transactions: [],
@@ -171,44 +172,85 @@ describe('Test function: sendTransaction', function () {
apiParams.requestParams = Object.assign({}, requestObject);
});
- describe('when require upgrade checking fail', function () {
- it('should throw error', async function () {
- const isUpgradeRequiredStub = sandbox.stub(utils, 'isUpgradeRequired').throws('network error');
- let result;
- try {
- result = await sendTransaction(apiParams);
- } catch (err) {
- result = err;
- } finally {
- expect(isUpgradeRequiredStub).to.have.been.calledOnceWith(STARKNET_TESTNET_NETWORK, account1.address);
- expect(result).to.be.an('Error');
- }
+ describe('when account is cairo 0', function () {
+ describe('when require upgrade checking fail', function () {
+ it('should throw error', async function () {
+ const isUpgradeRequiredStub = sandbox.stub(utils, 'isUpgradeRequired').throws('network error');
+ let result;
+ try {
+ result = await sendTransaction(apiParams);
+ } catch (err) {
+ result = err;
+ } finally {
+ expect(isUpgradeRequiredStub).to.have.been.calledOnceWith(STARKNET_TESTNET_NETWORK, account1.address);
+ expect(result).to.be.an('Error');
+ }
+ });
});
- });
- describe('when account require upgrade', function () {
- let isUpgradeRequiredStub: sinon.SinonStub;
- beforeEach(async function () {
- isUpgradeRequiredStub = sandbox.stub(utils, 'isUpgradeRequired').resolves(true);
+ describe('when account require upgrade', function () {
+ let isUpgradeRequiredStub: sinon.SinonStub;
+ beforeEach(async function () {
+ isUpgradeRequiredStub = sandbox.stub(utils, 'isUpgradeRequired').resolves(true);
+ });
+
+ it('should throw error if upgrade required', async function () {
+ let result;
+ try {
+ result = await sendTransaction(apiParams);
+ } catch (err) {
+ result = err;
+ } finally {
+ expect(isUpgradeRequiredStub).to.have.been.calledOnceWith(STARKNET_TESTNET_NETWORK, account1.address);
+ expect(result).to.be.an('Error');
+ }
+ });
});
- it('should throw error if upgrade required', async function () {
- let result;
- try {
- result = await sendTransaction(apiParams);
- } catch (err) {
- result = err;
- } finally {
- expect(isUpgradeRequiredStub).to.have.been.calledOnceWith(STARKNET_TESTNET_NETWORK, account1.address);
- expect(result).to.be.an('Error');
- }
+ describe('when account do not require upgrade', function () {
+ let executeTxnResp;
+ beforeEach(async function () {
+ sandbox.stub(utils, 'isUpgradeRequired').resolves(false);
+ sandbox.stub(estimateFeeSnap, 'estimateFee').resolves({
+ suggestedMaxFee: estimateFeeResp.suggestedMaxFee.toString(10),
+ overallFee: estimateFeeResp.overall_fee.toString(10),
+ gasConsumed: '0',
+ gasPrice: '0',
+ unit: 'wei',
+ includeDeploy: true,
+ });
+ executeTxnResp = sendTransactionResp;
+ sandbox.stub(utils, 'executeTxn').resolves(executeTxnResp);
+ walletStub.rpcStubs.snap_manageState.resolves(state);
+ walletStub.rpcStubs.snap_dialog.resolves(true);
+ });
+ describe('when account is deployed', function () {
+ beforeEach(async function () {
+ sandbox.stub(utils, 'isAccountAddressDeployed').resolves(true);
+ });
+
+ it('should send a transaction for transferring 10 tokens correctly', async function () {
+ const result = await sendTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(walletStub.rpcStubs.snap_manageState).to.have.been.called;
+ expect(result).to.be.eql(sendTransactionResp);
+ });
+ });
+
+ describe('when account is not deployed', function () {
+ // not support cario0 address not deployed account
+ });
});
});
- describe('when account is not require upgrade', function () {
+ describe('when account is cairo 1', function () {
let executeTxnResp;
let executeTxnStub: sinon.SinonStub;
beforeEach(async function () {
+ apiParams.requestParams = {
+ ...apiParams.requestParams,
+ senderAddress: Cario1Account1.address,
+ };
sandbox.stub(utils, 'isUpgradeRequired').resolves(false);
sandbox.stub(estimateFeeSnap, 'estimateFee').resolves({
suggestedMaxFee: estimateFeeResp.suggestedMaxFee.toString(10),
@@ -221,252 +263,178 @@ describe('Test function: sendTransaction', function () {
executeTxnResp = sendTransactionResp;
executeTxnStub = sandbox.stub(utils, 'executeTxn').resolves(executeTxnResp);
walletStub.rpcStubs.snap_manageState.resolves(state);
+ walletStub.rpcStubs.snap_dialog.resolves(true);
});
- it('should return false if user rejected to sign the transaction', async function () {
- sandbox.stub(utils, 'isAccountAddressDeployed').resolves(true);
- walletStub.rpcStubs.snap_dialog.resolves(false);
- apiParams.requestParams = requestObject;
- const result = await sendTransaction(apiParams);
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
- expect(walletStub.rpcStubs.snap_manageState).not.to.have.been.called;
- expect(result).to.be.eql(false);
- });
-
- it('should use heading, text and copyable component', async function () {
- sandbox.stub(utils, 'isAccountAddressDeployed').resolves(true);
- executeTxnResp = sendTransactionFailedResp;
- const requestObject: SendTransactionRequestParams = {
- contractAddress: account1.address,
- contractFuncName: 'get_signer',
- contractCallData: '**foo**',
- senderAddress: account1.address,
- };
- apiParams.requestParams = requestObject;
- await sendTransaction(apiParams);
- const expectedDialogParams = {
- type: 'confirmation',
- content: {
- type: 'panel',
- children: [
- { type: 'heading', value: 'Do you want to sign this transaction ?' },
- {
- type: 'text',
- value: `**Signer Address:**`,
- },
- {
- type: 'copyable',
- value: '0x04882a372da3dfe1c53170ad75893832469bf87b62b13e84662565c4a88f25cd',
- },
- {
- type: 'text',
- value: `**Contract:**`,
- },
- {
- type: 'copyable',
- value: '0x04882a372da3dfe1c53170ad75893832469bf87b62b13e84662565c4a88f25cd',
- },
- {
- type: 'text',
- value: `**Call Data:**`,
- },
- {
- type: 'copyable',
- value: '[**foo**]',
- },
- {
- type: 'text',
- value: `**Estimated Gas Fee(ETH):**`,
- },
- {
- type: 'copyable',
- value: '0.000022702500105945',
- },
- {
- type: 'text',
- value: `**Network:**`,
- },
- {
- type: 'copyable',
- value: 'Goerli Testnet',
- },
- ],
- },
- };
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledWith(expectedDialogParams);
- });
-
- describe('when account is cairo 0', function () {
- //TODO
- });
-
- describe('when account is cairo 1', function () {
+ describe('when account is deployed', function () {
beforeEach(async function () {
- walletStub.rpcStubs.snap_dialog.resolves(true);
+ sandbox.stub(utils, 'isAccountAddressDeployed').resolves(true);
});
- describe('when account is deployed', function () {
- beforeEach(async function () {
- sandbox.stub(utils, 'isAccountAddressDeployed').resolves(true);
- });
+ it('should send a transaction for transferring 10 tokens correctly', async function () {
+ const result = await sendTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(walletStub.rpcStubs.snap_manageState).to.have.been.called;
+ expect(result).to.be.eql(sendTransactionResp);
+ });
- it('should send a transaction for transferring 10 tokens correctly', async function () {
- const requestObject: SendTransactionRequestParams = {
- contractAddress: '0x07394cbe418daa16e42b87ba67372d4ab4a5df0b05c6e554d158458ce245bc10',
- contractFuncName: 'transfer',
- contractCallData:
- '0x0256d8f49882cc9366037415f48fa9fd2b5b7344ded7573ebfcef7c90e3e6b75,100000000000000000000,0',
- senderAddress: account1.address,
- };
- apiParams.requestParams = requestObject;
- const result = await sendTransaction(apiParams);
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
- expect(walletStub.rpcStubs.snap_manageState).to.have.been.called;
- expect(result).to.be.eql(sendTransactionResp);
- });
+ it('should send a transaction for transferring 10 tokens but not update snap state if transaction_hash is missing from response', async function () {
+ executeTxnStub.restore();
+ executeTxnStub = sandbox.stub(utils, 'executeTxn').resolves(sendTransactionFailedResp);
+ const result = await sendTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(walletStub.rpcStubs.snap_manageState).not.to.have.been.called;
+ expect(result).to.be.eql(sendTransactionFailedResp);
+ });
- it('should send a transaction for transferring 10 tokens but not update snap state if transaction_hash is missing from response', async function () {
- executeTxnStub.restore();
- executeTxnStub = sandbox.stub(utils, 'executeTxn').resolves(sendTransactionFailedResp);
- const requestObject: SendTransactionRequestParams = {
- contractAddress: '0x07394cbe418daa16e42b87ba67372d4ab4a5df0b05c6e554d158458ce245bc10',
- contractFuncName: 'transfer',
- contractCallData:
- '0x0256d8f49882cc9366037415f48fa9fd2b5b7344ded7573ebfcef7c90e3e6b75,100000000000000000000,0',
- senderAddress: account1.address,
- };
- apiParams.requestParams = requestObject;
- const result = await sendTransaction(apiParams);
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
- expect(walletStub.rpcStubs.snap_manageState).not.to.have.been.called;
- expect(result).to.be.eql(sendTransactionFailedResp);
- });
+ it('should send a transaction with given max fee for transferring 10 tokens correctly', async function () {
+ const apiRequest = apiParams.requestParams as SendTransactionRequestParams;
+ apiRequest.maxFee = '15135825227039';
+ const result = await sendTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(walletStub.rpcStubs.snap_manageState).to.have.been.called;
+ expect(result).to.be.eql(sendTransactionResp);
+ });
- it('should send a transaction with given max fee for transferring 10 tokens correctly', async function () {
- const requestObject: SendTransactionRequestParams = {
- contractAddress: '0x07394cbe418daa16e42b87ba67372d4ab4a5df0b05c6e554d158458ce245bc10',
- contractFuncName: 'transfer',
- contractCallData:
- '0x0256d8f49882cc9366037415f48fa9fd2b5b7344ded7573ebfcef7c90e3e6b75,100000000000000000000,0',
- senderAddress: account1.address,
- maxFee: '15135825227039',
- };
- apiParams.requestParams = requestObject;
- const result = await sendTransaction(apiParams);
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
- expect(walletStub.rpcStubs.snap_manageState).to.have.been.called;
- expect(result).to.be.eql(sendTransactionResp);
- });
+ it('should send a transfer transaction for empty call data', async function () {
+ const apiRequest = apiParams.requestParams as SendTransactionRequestParams;
+ apiRequest.contractCallData = undefined;
+ const result = await sendTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(walletStub.rpcStubs.snap_manageState).to.have.been.called;
+ expect(result).to.be.eql(sendTransactionResp);
+ });
- it('should send a transfer transaction for empty call data', async function () {
- const requestObject: SendTransactionRequestParams = {
- contractAddress: '0x07394cbe418daa16e42b87ba67372d4ab4a5df0b05c6e554d158458ce245bc10',
- contractFuncName: 'transfer',
- contractCallData: undefined,
- senderAddress: account1.address,
- };
- apiParams.requestParams = requestObject;
- const result = await sendTransaction(apiParams);
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
- expect(walletStub.rpcStubs.snap_manageState).to.have.been.called;
- expect(result).to.be.eql(sendTransactionResp);
- });
+ it('should send a transaction for empty call data', async function () {
+ const apiRequest = apiParams.requestParams as SendTransactionRequestParams;
+ apiRequest.contractCallData = undefined;
+ apiRequest.contractFuncName = 'get_signer';
+ const result = await sendTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(walletStub.rpcStubs.snap_manageState).to.have.been.called;
+ expect(result).to.be.eql(sendTransactionResp);
+ });
- it('should send a transaction for empty call data', async function () {
- const requestObject: SendTransactionRequestParams = {
- contractAddress: account1.address,
- contractFuncName: 'get_signer',
- contractCallData: undefined,
- senderAddress: account1.address,
- };
- apiParams.requestParams = requestObject;
- const result = await sendTransaction(apiParams);
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
- expect(walletStub.rpcStubs.snap_manageState).to.have.been.called;
- expect(result).to.be.eql(sendTransactionResp);
- });
+ it('should send a transaction for transferring 10 tokens from an unfound user correctly', async function () {
+ const apiRequest = apiParams.requestParams as SendTransactionRequestParams;
+ apiRequest.senderAddress = unfoundUserAddress;
+ const result = await sendTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(walletStub.rpcStubs.snap_manageState).to.have.been.called;
+ expect(result).to.be.eql(sendTransactionResp);
+ });
- it('should send a transaction for transferring 10 tokens from an unfound user correctly', async function () {
- const requestObject: SendTransactionRequestParams = {
- contractAddress: '0x07394cbe418daa16e42b87ba67372d4ab4a5df0b05c6e554d158458ce245bc10',
- contractFuncName: 'transfer',
- contractCallData:
- '0x0256d8f49882cc9366037415f48fa9fd2b5b7344ded7573ebfcef7c90e3e6b75,100000000000000000000,0',
- senderAddress: unfoundUserAddress,
- };
- apiParams.requestParams = requestObject;
- const result = await sendTransaction(apiParams);
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
- expect(walletStub.rpcStubs.snap_manageState).to.have.been.called;
- expect(result).to.be.eql(sendTransactionResp);
- });
+ it('should throw error if upsertTransaction failed', async function () {
+ sandbox.stub(snapUtils, 'upsertTransaction').throws(new Error());
+ let result;
+ try {
+ await sendTransaction(apiParams);
+ } catch (err) {
+ result = err;
+ } finally {
+ expect(result).to.be.an('Error');
+ }
+ });
- it('should send a transaction for transferring 10 tokens (token of 10 decimal places) from an unfound user correctly', async function () {
- const requestObject: SendTransactionRequestParams = {
- contractAddress: '0x06a09ccb1caaecf3d9683efe335a667b2169a409d19c589ba1eb771cd210af75',
- contractFuncName: 'transfer',
- contractCallData:
- '0x0256d8f49882cc9366037415f48fa9fd2b5b7344ded7573ebfcef7c90e3e6b75,100000000000000000000,0',
- senderAddress: unfoundUserAddress,
- };
- apiParams.requestParams = requestObject;
- const result = await sendTransaction(apiParams);
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
- expect(walletStub.rpcStubs.snap_manageState).to.have.been.called;
- expect(result).to.be.eql(sendTransactionResp);
- });
+ it('should return false if user rejected to sign the transaction', async function () {
+ walletStub.rpcStubs.snap_dialog.resolves(false);
+ const result = await sendTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(walletStub.rpcStubs.snap_manageState).not.to.have.been.called;
+ expect(result).to.be.eql(false);
+ });
- it('should throw error if upsertTransaction failed', async function () {
- sandbox.stub(snapUtils, 'upsertTransaction').throws(new Error());
- const requestObject: SendTransactionRequestParams = {
- contractAddress: '0x07394cbe418daa16e42b87ba67372d4ab4a5df0b05c6e554d158458ce245bc10',
- contractFuncName: 'transfer',
- contractCallData:
- '0x0256d8f49882cc9366037415f48fa9fd2b5b7344ded7573ebfcef7c90e3e6b75,100000000000000000000,0',
- senderAddress: unfoundUserAddress,
- };
- apiParams.requestParams = requestObject;
-
- let result;
- try {
- await sendTransaction(apiParams);
- } catch (err) {
- result = err;
- } finally {
- expect(result).to.be.an('Error');
- }
- });
+ it('should use heading, text and copyable component', async function () {
+ executeTxnResp = sendTransactionFailedResp;
+ const requestObject: SendTransactionRequestParams = {
+ contractAddress: account1.address,
+ contractFuncName: 'get_signer',
+ contractCallData: '**foo**',
+ senderAddress: account1.address,
+ };
+ apiParams.requestParams = requestObject;
+ await sendTransaction(apiParams);
+ const expectedDialogParams = {
+ type: 'confirmation',
+ content: {
+ type: 'panel',
+ children: [
+ { type: 'heading', value: 'Do you want to sign this transaction ?' },
+ {
+ type: 'text',
+ value: `**Signer Address:**`,
+ },
+ {
+ type: 'copyable',
+ value: '0x04882a372da3dfe1c53170ad75893832469bf87b62b13e84662565c4a88f25cd',
+ },
+ {
+ type: 'text',
+ value: `**Contract:**`,
+ },
+ {
+ type: 'copyable',
+ value: '0x04882a372da3dfe1c53170ad75893832469bf87b62b13e84662565c4a88f25cd',
+ },
+ {
+ type: 'text',
+ value: `**Call Data:**`,
+ },
+ {
+ type: 'copyable',
+ value: '[**foo**]',
+ },
+ {
+ type: 'text',
+ value: `**Estimated Gas Fee(ETH):**`,
+ },
+ {
+ type: 'copyable',
+ value: '0.000022702500105945',
+ },
+ {
+ type: 'text',
+ value: `**Network:**`,
+ },
+ {
+ type: 'copyable',
+ value: 'Goerli Testnet',
+ },
+ ],
+ },
+ };
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledWith(expectedDialogParams);
});
+ });
- describe('when account is not deployed', function () {
- beforeEach(async function () {
- sandbox.stub(utils, 'isAccountAddressDeployed').resolves(false);
- });
+ describe('when account is not deployed', function () {
+ beforeEach(async function () {
+ sandbox.stub(utils, 'isAccountAddressDeployed').resolves(false);
+ });
- it('should send a transaction for transferring 10 tokens and a transaction for deploy correctly', async function () {
- sandbox.stub(utils, 'deployAccount').callsFake(async () => {
- return createAccountProxyResp;
- });
- sandbox.stub(utils, 'getBalance').callsFake(async () => {
- return getBalanceResp[0];
- });
- sandbox.stub(utils, 'estimateAccountDeployFee').callsFake(async () => {
- return estimateDeployFeeResp;
- });
- const requestObject: SendTransactionRequestParams = {
- contractAddress: '0x07394cbe418daa16e42b87ba67372d4ab4a5df0b05c6e554d158458ce245bc10',
- contractFuncName: 'transfer',
- contractCallData:
- '0x0256d8f49882cc9366037415f48fa9fd2b5b7344ded7573ebfcef7c90e3e6b75,100000000000000000000,0',
- senderAddress: account1.address,
- };
- apiParams.requestParams = requestObject;
- const result = await sendTransaction(apiParams);
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
- expect(walletStub.rpcStubs.snap_manageState).to.have.been.called;
- expect(result).to.be.eql(sendTransactionResp);
+ it('should send a transaction for transferring 10 tokens and a transaction for deploy correctly', async function () {
+ sandbox.stub(utils, 'deployAccount').callsFake(async () => {
+ return createAccountProxyResp;
+ });
+ sandbox.stub(utils, 'getBalance').callsFake(async () => {
+ return getBalanceResp[0];
+ });
+ sandbox.stub(utils, 'estimateAccountDeployFee').callsFake(async () => {
+ return estimateDeployFeeResp;
});
+ const requestObject: SendTransactionRequestParams = {
+ contractAddress: '0x07394cbe418daa16e42b87ba67372d4ab4a5df0b05c6e554d158458ce245bc10',
+ contractFuncName: 'transfer',
+ contractCallData:
+ '0x0256d8f49882cc9366037415f48fa9fd2b5b7344ded7573ebfcef7c90e3e6b75,100000000000000000000,0',
+ senderAddress: account1.address,
+ };
+ apiParams.requestParams = requestObject;
+ const result = await sendTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(walletStub.rpcStubs.snap_manageState).to.have.been.called;
+ expect(result).to.be.eql(sendTransactionResp);
});
});
});
diff --git a/packages/starknet-snap/test/src/signDeclareTransaction.test.ts b/packages/starknet-snap/test/src/signDeclareTransaction.test.ts
new file mode 100644
index 00000000..68d30b72
--- /dev/null
+++ b/packages/starknet-snap/test/src/signDeclareTransaction.test.ts
@@ -0,0 +1,112 @@
+import chai, { expect } from 'chai';
+import sinon from 'sinon';
+import sinonChai from 'sinon-chai';
+import { WalletMock } from '../wallet.mock.test';
+import { signDeclareTransaction } from '../../src/signDeclareTransaction';
+import { SnapState } from '../../src/types/snapState';
+import { STARKNET_MAINNET_NETWORK, STARKNET_TESTNET_NETWORK } from '../../src/utils/constants';
+import { createAccountProxyTxn, getBip44EntropyStub, account1, signature3 } from '../constants.test';
+import { getAddressKeyDeriver } from '../../src/utils/keyPair';
+import { Mutex } from 'async-mutex';
+import { ApiParams, SignDeclareTransactionRequestParams } from '../../src/types/snapApi';
+import { constants } from 'starknet';
+import * as utils from '../../src/utils/starknetUtils';
+
+chai.use(sinonChai);
+const sandbox = sinon.createSandbox();
+
+describe('Test function: signDeclareTransaction', function () {
+ this.timeout(10000);
+ const walletStub = new WalletMock();
+ const state: SnapState = {
+ accContracts: [],
+ erc20Tokens: [],
+ networks: [STARKNET_MAINNET_NETWORK, STARKNET_TESTNET_NETWORK],
+ transactions: [],
+ };
+ const apiParams: ApiParams = {
+ state,
+ requestParams: {},
+ wallet: walletStub,
+ saveMutex: new Mutex(),
+ };
+
+ const requestObject: SignDeclareTransactionRequestParams = {
+ chainId: STARKNET_TESTNET_NETWORK.chainId,
+ signerAddress: account1.address,
+ transaction: {
+ classHash: '0x025ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918',
+ senderAddress: account1.address,
+ chainId: constants.StarknetChainId.SN_GOERLI,
+ nonce: '0x1',
+ version: '0x0',
+ maxFee: 100,
+ },
+ enableAutherize: true,
+ };
+
+ beforeEach(async function () {
+ walletStub.rpcStubs.snap_getBip44Entropy.callsFake(getBip44EntropyStub);
+ apiParams.keyDeriver = await getAddressKeyDeriver(walletStub);
+ apiParams.requestParams = requestObject;
+ sandbox.useFakeTimers(createAccountProxyTxn.timestamp);
+ walletStub.rpcStubs.snap_dialog.resolves(true);
+ walletStub.rpcStubs.snap_manageState.resolves(state);
+ });
+
+ afterEach(function () {
+ walletStub.reset();
+ sandbox.restore();
+ apiParams.requestParams = requestObject;
+ });
+
+ it('should sign a transaction from an user account correctly', async function () {
+ sandbox.stub(utils, 'signDeclareTransaction').resolves(signature3);
+ const result = await signDeclareTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(result).to.be.eql(signature3);
+ });
+
+ it('should throw error if signDeclareTransaction fail', async function () {
+ sandbox.stub(utils, 'signDeclareTransaction').throws(new Error());
+ let result;
+ try {
+ await signDeclareTransaction(apiParams);
+ } catch (err) {
+ result = err;
+ } finally {
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(result).to.be.an('Error');
+ }
+ });
+
+ it('should return false if user deny to sign the transaction', async function () {
+ const stub = sandbox.stub(utils, 'signDeclareTransaction');
+ walletStub.rpcStubs.snap_dialog.resolves(false);
+
+ const result = await signDeclareTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(stub).to.have.been.callCount(0);
+ expect(result).to.be.eql(false);
+ });
+
+ it('should skip dialog if enableAutherize is false', async function () {
+ sandbox.stub(utils, 'signDeclareTransaction').resolves(signature3);
+ const paramsObject = apiParams.requestParams as SignDeclareTransactionRequestParams;
+ paramsObject.enableAutherize = false;
+ const result = await signDeclareTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.callCount(0);
+ expect(result).to.be.eql(signature3);
+ paramsObject.enableAutherize = true;
+ });
+
+ it('should skip dialog if enableAutherize is omit', async function () {
+ sandbox.stub(utils, 'signDeclareTransaction').resolves(signature3);
+ const paramsObject = apiParams.requestParams as SignDeclareTransactionRequestParams;
+ paramsObject.enableAutherize = undefined;
+ const result = await signDeclareTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.callCount(0);
+ expect(result).to.be.eql(signature3);
+ paramsObject.enableAutherize = true;
+ });
+});
diff --git a/packages/starknet-snap/test/src/signDeployAccountTransaction.test.ts b/packages/starknet-snap/test/src/signDeployAccountTransaction.test.ts
new file mode 100644
index 00000000..88c6db54
--- /dev/null
+++ b/packages/starknet-snap/test/src/signDeployAccountTransaction.test.ts
@@ -0,0 +1,114 @@
+import chai, { expect } from 'chai';
+import sinon from 'sinon';
+import sinonChai from 'sinon-chai';
+import { WalletMock } from '../wallet.mock.test';
+import { signDeployAccountTransaction } from '../../src/signDeployAccountTransaction';
+import { SnapState } from '../../src/types/snapState';
+import { STARKNET_MAINNET_NETWORK, STARKNET_TESTNET_NETWORK } from '../../src/utils/constants';
+import { createAccountProxyTxn, getBip44EntropyStub, account1, signature3 } from '../constants.test';
+import { getAddressKeyDeriver } from '../../src/utils/keyPair';
+import { Mutex } from 'async-mutex';
+import { ApiParams, SignDeployAccountTransactionRequestParams } from '../../src/types/snapApi';
+import { constants } from 'starknet';
+import * as utils from '../../src/utils/starknetUtils';
+
+chai.use(sinonChai);
+const sandbox = sinon.createSandbox();
+
+describe('Test function: signDeployAccountTransaction', function () {
+ this.timeout(10000);
+ const walletStub = new WalletMock();
+ const state: SnapState = {
+ accContracts: [],
+ erc20Tokens: [],
+ networks: [STARKNET_MAINNET_NETWORK, STARKNET_TESTNET_NETWORK],
+ transactions: [],
+ };
+ const apiParams: ApiParams = {
+ state,
+ requestParams: {},
+ wallet: walletStub,
+ saveMutex: new Mutex(),
+ };
+
+ const requestObject: SignDeployAccountTransactionRequestParams = {
+ chainId: STARKNET_TESTNET_NETWORK.chainId,
+ signerAddress: account1.address,
+ transaction: {
+ classHash: '0x025ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918',
+ contractAddress: account1.address,
+ constructorCalldata: [],
+ addressSalt: '0x025ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918',
+ chainId: constants.StarknetChainId.SN_MAIN,
+ nonce: '0x1',
+ version: '0x0',
+ maxFee: 100,
+ },
+ enableAutherize: true,
+ };
+
+ beforeEach(async function () {
+ walletStub.rpcStubs.snap_getBip44Entropy.callsFake(getBip44EntropyStub);
+ apiParams.keyDeriver = await getAddressKeyDeriver(walletStub);
+ apiParams.requestParams = requestObject;
+ sandbox.useFakeTimers(createAccountProxyTxn.timestamp);
+ walletStub.rpcStubs.snap_dialog.resolves(true);
+ walletStub.rpcStubs.snap_manageState.resolves(state);
+ });
+
+ afterEach(function () {
+ walletStub.reset();
+ sandbox.restore();
+ apiParams.requestParams = requestObject;
+ });
+
+ it('should sign a transaction from an user account correctly', async function () {
+ sandbox.stub(utils, 'signDeployAccountTransaction').resolves(signature3);
+ const result = await signDeployAccountTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(result).to.be.eql(signature3);
+ });
+
+ it('should throw error if signDeployAccountTransaction fail', async function () {
+ sandbox.stub(utils, 'signDeployAccountTransaction').throws(new Error());
+ let result;
+ try {
+ await signDeployAccountTransaction(apiParams);
+ } catch (err) {
+ result = err;
+ } finally {
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(result).to.be.an('Error');
+ }
+ });
+
+ it('should return false if user deny to sign the transaction', async function () {
+ const stub = sandbox.stub(utils, 'signDeployAccountTransaction');
+ walletStub.rpcStubs.snap_dialog.resolves(false);
+
+ const result = await signDeployAccountTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(stub).to.have.been.callCount(0);
+ expect(result).to.be.eql(false);
+ });
+
+ it('should skip dialog if enableAutherize is false', async function () {
+ sandbox.stub(utils, 'signDeployAccountTransaction').resolves(signature3);
+ const paramsObject = apiParams.requestParams as SignDeployAccountTransactionRequestParams;
+ paramsObject.enableAutherize = false;
+ const result = await signDeployAccountTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.callCount(0);
+ expect(result).to.be.eql(signature3);
+ paramsObject.enableAutherize = true;
+ });
+
+ it('should skip dialog if enableAutherize is omit', async function () {
+ sandbox.stub(utils, 'signDeployAccountTransaction').resolves(signature3);
+ const paramsObject = apiParams.requestParams as SignDeployAccountTransactionRequestParams;
+ paramsObject.enableAutherize = undefined;
+ const result = await signDeployAccountTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.callCount(0);
+ expect(result).to.be.eql(signature3);
+ paramsObject.enableAutherize = true;
+ });
+});
diff --git a/packages/starknet-snap/test/src/signMessage.test.ts b/packages/starknet-snap/test/src/signMessage.test.ts
index b3d07835..2174004f 100644
--- a/packages/starknet-snap/test/src/signMessage.test.ts
+++ b/packages/starknet-snap/test/src/signMessage.test.ts
@@ -1,4 +1,3 @@
-import { toJson } from '../../src/utils/serializer';
import chai, { expect } from 'chai';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
@@ -7,7 +6,15 @@ import { SnapState } from '../../src/types/snapState';
import { signMessage } from '../../src/signMessage';
import typedDataExample from '../../src/typedData/typedDataExample.json';
import { STARKNET_TESTNET_NETWORK } from '../../src/utils/constants';
-import { account1, getBip44EntropyStub, signature1, signature2, unfoundUserAddress } from '../constants.test';
+import {
+ account1,
+ Cario1Account1,
+ getBip44EntropyStub,
+ signature4SignMessageWithUnfoundAddress,
+ unfoundUserAddress,
+ signature4SignMessage,
+ signature4Cario1SignMessage,
+} from '../constants.test';
import { getAddressKeyDeriver } from '../../src/utils/keyPair';
import * as utils from '../../src/utils/starknetUtils';
import { Mutex } from 'async-mutex';
@@ -20,7 +27,7 @@ describe('Test function: signMessage', function () {
this.timeout(5000);
const walletStub = new WalletMock();
const state: SnapState = {
- accContracts: [account1],
+ accContracts: [],
erc20Tokens: [],
networks: [STARKNET_TESTNET_NETWORK],
transactions: [],
@@ -33,13 +40,16 @@ describe('Test function: signMessage', function () {
};
const requestObject: SignMessageRequestParams = {
+ chainId: STARKNET_TESTNET_NETWORK.chainId,
signerAddress: account1.address,
- typedDataMessage: toJson(typedDataExample),
+ typedDataMessage: typedDataExample,
+ enableAutherize: true,
};
beforeEach(async function () {
walletStub.rpcStubs.snap_getBip44Entropy.callsFake(getBip44EntropyStub);
apiParams.keyDeriver = await getAddressKeyDeriver(walletStub);
+ apiParams.requestParams = requestObject;
walletStub.rpcStubs.snap_dialog.resolves(true);
});
@@ -92,134 +102,116 @@ describe('Test function: signMessage', function () {
apiParams.requestParams = Object.assign({}, requestObject);
});
- describe('when require upgrade checking fail', function () {
- it('should throw error', async function () {
- const isUpgradeRequiredStub = sandbox.stub(utils, 'isUpgradeRequired').throws('network error');
- let result;
- try {
- result = await signMessage(apiParams);
- } catch (err) {
- result = err;
- } finally {
- expect(isUpgradeRequiredStub).to.have.been.calledOnceWith(STARKNET_TESTNET_NETWORK, account1.address);
- expect(result).to.be.an('Error');
- }
+ describe('when account is cairo 0', function () {
+ describe('when require upgrade checking fail', function () {
+ it('should throw error', async function () {
+ const isUpgradeRequiredStub = sandbox.stub(utils, 'isUpgradeRequired').throws('network error');
+ let result;
+ try {
+ result = await signMessage(apiParams);
+ } catch (err) {
+ result = err;
+ } finally {
+ expect(isUpgradeRequiredStub).to.have.been.calledOnceWith(STARKNET_TESTNET_NETWORK, account1.address);
+ expect(result).to.be.an('Error');
+ }
+ });
+ });
+
+ describe('when account require upgrade', function () {
+ let isUpgradeRequiredStub: sinon.SinonStub;
+ beforeEach(async function () {
+ isUpgradeRequiredStub = sandbox.stub(utils, 'isUpgradeRequired').resolves(true);
+ });
+
+ it('should throw error if upgrade required', async function () {
+ let result;
+ try {
+ result = await signMessage(apiParams);
+ } catch (err) {
+ result = err;
+ } finally {
+ expect(isUpgradeRequiredStub).to.have.been.calledOnceWith(STARKNET_TESTNET_NETWORK, account1.address);
+ expect(result).to.be.an('Error');
+ }
+ });
+ });
+
+ describe('when account is not require upgrade', function () {
+ beforeEach(async function () {
+ sandbox.stub(utils, 'isUpgradeRequired').resolves(false);
+ });
+
+ it('should sign a message from an user account correctly', async function () {
+ const result = await signMessage(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(walletStub.rpcStubs.snap_manageState).not.to.have.been.called;
+ expect(result).to.be.eql(signature4SignMessage);
+ });
});
});
- describe('when account require upgrade', function () {
- let isUpgradeRequiredStub: sinon.SinonStub;
+ describe('when account is cairo 1', function () {
beforeEach(async function () {
- isUpgradeRequiredStub = sandbox.stub(utils, 'isUpgradeRequired').resolves(true);
+ apiParams.requestParams = {
+ ...apiParams.requestParams,
+ signerAddress: Cario1Account1.address,
+ };
+ sandbox.stub(utils, 'isUpgradeRequired').resolves(false);
+ });
+
+ it('should sign a message from an user account correctly', async function () {
+ const result = await signMessage(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(walletStub.rpcStubs.snap_manageState).not.to.have.been.called;
+ expect(result).to.be.eql(signature4Cario1SignMessage);
+ });
+
+ it('should sign a message from an unfound user account correctly', async function () {
+ const paramsObject = apiParams.requestParams as SignMessageRequestParams;
+ paramsObject.signerAddress = unfoundUserAddress;
+ const result = await signMessage(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(walletStub.rpcStubs.snap_manageState).not.to.have.been.called;
+ expect(result).to.be.eql(signature4SignMessageWithUnfoundAddress);
});
- it('should throw error if upgrade required', async function () {
+ it('should throw error if getKeysFromAddress failed', async function () {
+ sandbox.stub(utils, 'getKeysFromAddress').throws(new Error());
let result;
try {
- result = await signMessage(apiParams);
+ await signMessage(apiParams);
} catch (err) {
result = err;
} finally {
- expect(isUpgradeRequiredStub).to.have.been.calledOnceWith(STARKNET_TESTNET_NETWORK, account1.address);
expect(result).to.be.an('Error');
}
- });
- });
-
- describe('when account is not require upgrade', function () {
- beforeEach(async function () {
- sandbox.stub(utils, 'isUpgradeRequired').resolves(false);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(walletStub.rpcStubs.snap_manageState).not.to.have.been.called;
});
it('should return false if the user not confirmed', async function () {
walletStub.rpcStubs.snap_dialog.resolves(false);
- const requestObject: SignMessageRequestParams = {
- signerAddress: account1.address,
- typedDataMessage: undefined, // will use typedDataExample.json
- };
- apiParams.requestParams = requestObject;
const result = await signMessage(apiParams);
expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
expect(walletStub.rpcStubs.snap_manageState).not.to.have.been.called;
expect(result).to.be.eql(false);
});
+ });
- describe('when account is cairo 0', function () {
- //TODO
- });
+ it('should skip dialog if enableAutherize is false or omit', async function () {
+ sandbox.stub(utils, 'isUpgradeRequired').resolves(false);
+ const paramsObject = apiParams.requestParams as SignMessageRequestParams;
- describe('when account is cairo 1', function () {
- it('should sign a message from an user account correctly', async function () {
- const requestObject: SignMessageRequestParams = {
- signerAddress: account1.address,
- typedDataMessage: undefined, // will use typedDataExample.json
- };
- apiParams.requestParams = requestObject;
- const result: boolean | string = await signMessage(apiParams);
- const expectedDialogParams = {
- type: 'confirmation',
- content: {
- type: 'panel',
- children: [
- { type: 'heading', value: 'Do you want to sign this message ?' },
-
- {
- type: 'text',
- value: `**Message:**`,
- },
- {
- type: 'copyable',
- value: toJson(typedDataExample),
- },
- {
- type: 'text',
- value: `**Signer address:**`,
- },
- {
- type: 'copyable',
- value: `${account1.address}`,
- },
- ],
- },
- };
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledWith(expectedDialogParams);
- expect(walletStub.rpcStubs.snap_manageState).not.to.have.been.called;
- expect(result).to.be.eql(signature1);
- });
-
- it('should sign a message from an unfound user account correctly', async function () {
- const requestObject: SignMessageRequestParams = {
- signerAddress: unfoundUserAddress,
- typedDataMessage: toJson(typedDataExample),
- };
- apiParams.requestParams = requestObject;
- const result = await signMessage(apiParams);
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
- expect(walletStub.rpcStubs.snap_manageState).not.to.have.been.called;
- expect(result).to.be.eql(signature2);
- });
+ paramsObject.enableAutherize = false;
+ await signMessage(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.callCount(0);
- it('should throw error if getKeysFromAddress failed', async function () {
- sandbox.stub(utils, 'getKeysFromAddress').throws(new Error());
- const requestObject: SignMessageRequestParams = {
- signerAddress: account1.address,
- typedDataMessage: undefined, // will use typedDataExample.json
- };
- apiParams.requestParams = requestObject;
+ paramsObject.enableAutherize = undefined;
+ await signMessage(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.callCount(0);
- let result;
- try {
- await signMessage(apiParams);
- } catch (err) {
- result = err;
- } finally {
- expect(result).to.be.an('Error');
- }
- expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
- expect(walletStub.rpcStubs.snap_manageState).not.to.have.been.called;
- });
- });
+ paramsObject.enableAutherize = true;
});
});
});
diff --git a/packages/starknet-snap/test/src/signTransaction.test.ts b/packages/starknet-snap/test/src/signTransaction.test.ts
new file mode 100644
index 00000000..f978b53d
--- /dev/null
+++ b/packages/starknet-snap/test/src/signTransaction.test.ts
@@ -0,0 +1,121 @@
+import chai, { expect } from 'chai';
+import sinon from 'sinon';
+import sinonChai from 'sinon-chai';
+import { WalletMock } from '../wallet.mock.test';
+import { signTransaction } from '../../src/signTransaction';
+import { SnapState } from '../../src/types/snapState';
+import { STARKNET_MAINNET_NETWORK, STARKNET_TESTNET_NETWORK } from '../../src/utils/constants';
+import { createAccountProxyTxn, getBip44EntropyStub, account1, signature3 } from '../constants.test';
+import { getAddressKeyDeriver } from '../../src/utils/keyPair';
+import { Mutex } from 'async-mutex';
+import { ApiParams, SignTransactionRequestParams } from '../../src/types/snapApi';
+import { constants } from 'starknet';
+import * as utils from '../../src/utils/starknetUtils';
+
+chai.use(sinonChai);
+const sandbox = sinon.createSandbox();
+
+describe('Test function: signMessage', function () {
+ this.timeout(10000);
+ const walletStub = new WalletMock();
+ const state: SnapState = {
+ accContracts: [],
+ erc20Tokens: [],
+ networks: [STARKNET_MAINNET_NETWORK, STARKNET_TESTNET_NETWORK],
+ transactions: [],
+ };
+ const apiParams: ApiParams = {
+ state,
+ requestParams: {},
+ wallet: walletStub,
+ saveMutex: new Mutex(),
+ };
+
+ const requestObject: SignTransactionRequestParams = {
+ chainId: STARKNET_TESTNET_NETWORK.chainId,
+ signerAddress: account1.address,
+ transactions: [
+ {
+ entrypoint: 'transfer',
+ calldata: ['0', '0', '0'],
+ contractAddress: createAccountProxyTxn.contractAddress,
+ },
+ {
+ entrypoint: 'transfer2',
+ calldata: ['0', '0', '0'],
+ contractAddress: createAccountProxyTxn.contractAddress,
+ },
+ ],
+ transactionsDetail: {
+ walletAddress: '0x00b28a089e7fb83debee4607b6334d687918644796b47d9e9e38ea8213833137',
+ chainId: constants.StarknetChainId.SN_MAIN,
+ cairoVersion: '0',
+ nonce: '0x1',
+ version: '0x0',
+ maxFee: 100,
+ },
+ enableAutherize: true,
+ };
+
+ beforeEach(async function () {
+ walletStub.rpcStubs.snap_getBip44Entropy.callsFake(getBip44EntropyStub);
+ apiParams.keyDeriver = await getAddressKeyDeriver(walletStub);
+ apiParams.requestParams = requestObject;
+ sandbox.useFakeTimers(createAccountProxyTxn.timestamp);
+ walletStub.rpcStubs.snap_dialog.resolves(true);
+ walletStub.rpcStubs.snap_manageState.resolves(state);
+ });
+
+ afterEach(function () {
+ walletStub.reset();
+ sandbox.restore();
+ apiParams.requestParams = requestObject;
+ });
+
+ it('should sign a transaction from an user account correctly', async function () {
+ const result = await signTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(result).to.be.eql(signature3);
+ });
+
+ it('should throw error if signTransaction fail', async function () {
+ sandbox.stub(utils, 'signTransactions').throws(new Error());
+ let result;
+ try {
+ await signTransaction(apiParams);
+ } catch (err) {
+ result = err;
+ } finally {
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(result).to.be.an('Error');
+ }
+ });
+
+ it('should return false if user deny to sign the transaction', async function () {
+ const stub = sandbox.stub(utils, 'signTransactions');
+ walletStub.rpcStubs.snap_dialog.resolves(false);
+
+ const result = await signTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.calledOnce;
+ expect(stub).to.have.been.callCount(0);
+ expect(result).to.be.eql(false);
+ });
+
+ it('should skip dialog if enableAutherize is false', async function () {
+ const paramsObject = apiParams.requestParams as SignTransactionRequestParams;
+ paramsObject.enableAutherize = false;
+ const result = await signTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.callCount(0);
+ expect(result).to.be.eql(signature3);
+ paramsObject.enableAutherize = true;
+ });
+
+ it('should skip dialog if enableAutherize is omit', async function () {
+ const paramsObject = apiParams.requestParams as SignTransactionRequestParams;
+ paramsObject.enableAutherize = undefined;
+ const result = await signTransaction(apiParams);
+ expect(walletStub.rpcStubs.snap_dialog).to.have.been.callCount(0);
+ expect(result).to.be.eql(signature3);
+ paramsObject.enableAutherize = true;
+ });
+});
diff --git a/packages/starknet-snap/test/src/switchNetwork.test.ts b/packages/starknet-snap/test/src/switchNetwork.test.ts
new file mode 100644
index 00000000..e8cc4573
--- /dev/null
+++ b/packages/starknet-snap/test/src/switchNetwork.test.ts
@@ -0,0 +1,92 @@
+import chai, { expect } from 'chai';
+import sinon from 'sinon';
+import sinonChai from 'sinon-chai';
+import { WalletMock } from '../wallet.mock.test';
+import { SnapState } from '../../src/types/snapState';
+import * as snapUtils from '../../src/utils/snapUtils';
+import { STARKNET_MAINNET_NETWORK, STARKNET_TESTNET_NETWORK } from '../../src/utils/constants';
+import { Mutex } from 'async-mutex';
+import { SwitchNetworkRequestParams, ApiParams } from '../../src/types/snapApi';
+import { switchNetwork } from '../../src/switchNetwork';
+
+chai.use(sinonChai);
+const sandbox = sinon.createSandbox();
+
+describe('Test function: switchNetwork', function () {
+ const walletStub = new WalletMock();
+ const state: SnapState = {
+ accContracts: [],
+ erc20Tokens: [],
+ networks: [STARKNET_TESTNET_NETWORK, STARKNET_MAINNET_NETWORK],
+ transactions: [],
+ currentNetwork: STARKNET_TESTNET_NETWORK,
+ };
+ const apiParams: ApiParams = {
+ state,
+ requestParams: {},
+ wallet: walletStub,
+ saveMutex: new Mutex(),
+ };
+ let stateStub: sinon.SinonStub;
+ let dialogStub: sinon.SinonStub;
+ beforeEach(function () {
+ stateStub = walletStub.rpcStubs.snap_manageState;
+ dialogStub = walletStub.rpcStubs.snap_dialog;
+ stateStub.resolves(state);
+ dialogStub.resolves(true);
+ });
+
+ afterEach(function () {
+ walletStub.reset();
+ sandbox.restore();
+ });
+
+ it('should switch the network correctly', async function () {
+ const requestObject: SwitchNetworkRequestParams = {
+ chainId: STARKNET_MAINNET_NETWORK.chainId,
+ };
+ apiParams.requestParams = requestObject;
+ const result = await switchNetwork(apiParams);
+ expect(result).to.be.eql(true);
+ expect(stateStub).to.be.calledOnce;
+ expect(dialogStub).to.be.calledOnce;
+ expect(state.currentNetwork).to.be.eql(STARKNET_MAINNET_NETWORK);
+ expect(state.networks.length).to.be.eql(2);
+ });
+
+ it('should throw an error if network not found', async function () {
+ const requestObject: SwitchNetworkRequestParams = {
+ chainId: '123',
+ };
+ apiParams.requestParams = requestObject;
+ let result;
+ try {
+ await switchNetwork(apiParams);
+ } catch (err) {
+ result = err;
+ } finally {
+ expect(result).to.be.an('Error');
+ expect(stateStub).to.be.callCount(0);
+ expect(dialogStub).to.be.callCount(0);
+ expect(state.currentNetwork).to.be.eql(STARKNET_MAINNET_NETWORK);
+ }
+ });
+
+ it('should throw an error if setCurrentNetwork failed', async function () {
+ sandbox.stub(snapUtils, 'setCurrentNetwork').throws(new Error());
+ const requestObject: SwitchNetworkRequestParams = {
+ chainId: STARKNET_TESTNET_NETWORK.chainId,
+ };
+ apiParams.requestParams = requestObject;
+ let result;
+ try {
+ await switchNetwork(apiParams);
+ } catch (err) {
+ result = err;
+ } finally {
+ expect(result).to.be.an('Error');
+ expect(dialogStub).to.be.callCount(1);
+ expect(state.currentNetwork).to.be.eql(STARKNET_MAINNET_NETWORK);
+ }
+ });
+});
diff --git a/packages/starknet-snap/test/utils/starknetUtils.test.ts b/packages/starknet-snap/test/utils/starknetUtils.test.ts
index 5c50fe51..4835126d 100644
--- a/packages/starknet-snap/test/utils/starknetUtils.test.ts
+++ b/packages/starknet-snap/test/utils/starknetUtils.test.ts
@@ -253,14 +253,8 @@ describe('Test function: getCorrectContractAddress', function () {
it('should permutation both Cairo0 and Cario1 address', async function () {
await utils.getCorrectContractAddress(STARKNET_TESTNET_NETWORK, PK);
- expect(getAccContractAddressAndCallDataStub).to.have.been.calledOnceWith(
- STARKNET_TESTNET_NETWORK.accountClassHash,
- PK,
- );
- expect(getAccContractAddressAndCallDataCairo0Stub).to.have.been.calledOnceWith(
- STARKNET_TESTNET_NETWORK.accountClassHashV0,
- PK,
- );
+ expect(getAccContractAddressAndCallDataStub).to.have.been.calledOnceWith(PK);
+ expect(getAccContractAddressAndCallDataCairo0Stub).to.have.been.calledOnceWith(PK);
});
it('should return Cairo1 address with pubic key when Cario1 deployed', async function () {
diff --git a/packages/starknet-snap/test/utils/transaction/filter.test.ts b/packages/starknet-snap/test/utils/transaction/filter.test.ts
index fd207fcc..a05fe3c5 100644
--- a/packages/starknet-snap/test/utils/transaction/filter.test.ts
+++ b/packages/starknet-snap/test/utils/transaction/filter.test.ts
@@ -75,7 +75,7 @@ describe('Test function: getTransactions', function () {
it('Should filter transactions based on chainId', () => {
const orgChainId = transactions[0].chainId;
transactions[0].chainId = '99';
- const chainIdFilter = new filter.ChainIdFilter(Number(transactions[0].chainId));
+ const chainIdFilter = new filter.ChainIdFilter(transactions[0].chainId);
const filteredTxnList = filter.filterTransactions(transactions, [chainIdFilter]);
expect(filteredTxnList).to.have.lengthOf(1);
transactions[0].chainId = orgChainId;
diff --git a/packages/wallet-ui/package.json b/packages/wallet-ui/package.json
index 03f7cd49..e7867cb5 100644
--- a/packages/wallet-ui/package.json
+++ b/packages/wallet-ui/package.json
@@ -62,7 +62,7 @@
"react-scripts": "5.0.1",
"rimraf": "^3.0.2",
"typescript": "^4.7.4",
- "webpack": "5"
+ "webpack": "^5.76.0"
},
"resolutions": {
"@storybook/{app}/webpack": "^4",
diff --git a/yarn.lock b/yarn.lock
index c96d3337..aa94bbcb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -44,6 +44,16 @@ __metadata:
languageName: node
linkType: hard
+"@babel/code-frame@npm:^7.22.13":
+ version: 7.22.13
+ resolution: "@babel/code-frame@npm:7.22.13"
+ dependencies:
+ "@babel/highlight": ^7.22.13
+ chalk: ^2.4.2
+ checksum: 22e342c8077c8b77eeb11f554ecca2ba14153f707b85294fcf6070b6f6150aae88a7b7436dd88d8c9289970585f3fe5b9b941c5aa3aa26a6d5a8ef3f292da058
+ languageName: node
+ linkType: hard
+
"@babel/compat-data@npm:^7.17.7, @babel/compat-data@npm:^7.20.1, @babel/compat-data@npm:^7.20.5":
version: 7.21.0
resolution: "@babel/compat-data@npm:7.21.0"
@@ -124,6 +134,18 @@ __metadata:
languageName: node
linkType: hard
+"@babel/generator@npm:^7.23.0":
+ version: 7.23.0
+ resolution: "@babel/generator@npm:7.23.0"
+ dependencies:
+ "@babel/types": ^7.23.0
+ "@jridgewell/gen-mapping": ^0.3.2
+ "@jridgewell/trace-mapping": ^0.3.17
+ jsesc: ^2.5.1
+ checksum: 8efe24adad34300f1f8ea2add420b28171a646edc70f2a1b3e1683842f23b8b7ffa7e35ef0119294e1901f45bfea5b3dc70abe1f10a1917ccdfb41bed69be5f1
+ languageName: node
+ linkType: hard
+
"@babel/helper-annotate-as-pure@npm:^7.16.0, @babel/helper-annotate-as-pure@npm:^7.18.6":
version: 7.18.6
resolution: "@babel/helper-annotate-as-pure@npm:7.18.6"
@@ -229,6 +251,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-environment-visitor@npm:^7.22.20":
+ version: 7.22.20
+ resolution: "@babel/helper-environment-visitor@npm:7.22.20"
+ checksum: d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69
+ languageName: node
+ linkType: hard
+
"@babel/helper-explode-assignable-expression@npm:^7.18.6":
version: 7.18.6
resolution: "@babel/helper-explode-assignable-expression@npm:7.18.6"
@@ -248,6 +277,16 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-function-name@npm:^7.23.0":
+ version: 7.23.0
+ resolution: "@babel/helper-function-name@npm:7.23.0"
+ dependencies:
+ "@babel/template": ^7.22.15
+ "@babel/types": ^7.23.0
+ checksum: e44542257b2d4634a1f979244eb2a4ad8e6d75eb6761b4cfceb56b562f7db150d134bc538c8e6adca3783e3bc31be949071527aa8e3aab7867d1ad2d84a26e10
+ languageName: node
+ linkType: hard
+
"@babel/helper-hoist-variables@npm:^7.18.6":
version: 7.18.6
resolution: "@babel/helper-hoist-variables@npm:7.18.6"
@@ -257,6 +296,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-hoist-variables@npm:^7.22.5":
+ version: 7.22.5
+ resolution: "@babel/helper-hoist-variables@npm:7.22.5"
+ dependencies:
+ "@babel/types": ^7.22.5
+ checksum: 394ca191b4ac908a76e7c50ab52102669efe3a1c277033e49467913c7ed6f7c64d7eacbeabf3bed39ea1f41731e22993f763b1edce0f74ff8563fd1f380d92cc
+ languageName: node
+ linkType: hard
+
"@babel/helper-member-expression-to-functions@npm:^7.20.7, @babel/helper-member-expression-to-functions@npm:^7.21.0":
version: 7.21.0
resolution: "@babel/helper-member-expression-to-functions@npm:7.21.0"
@@ -369,6 +417,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-split-export-declaration@npm:^7.22.6":
+ version: 7.22.6
+ resolution: "@babel/helper-split-export-declaration@npm:7.22.6"
+ dependencies:
+ "@babel/types": ^7.22.5
+ checksum: e141cace583b19d9195f9c2b8e17a3ae913b7ee9b8120246d0f9ca349ca6f03cb2c001fd5ec57488c544347c0bb584afec66c936511e447fd20a360e591ac921
+ languageName: node
+ linkType: hard
+
"@babel/helper-string-parser@npm:^7.19.4":
version: 7.19.4
resolution: "@babel/helper-string-parser@npm:7.19.4"
@@ -376,6 +433,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-string-parser@npm:^7.22.5":
+ version: 7.22.5
+ resolution: "@babel/helper-string-parser@npm:7.22.5"
+ checksum: 836851ca5ec813077bbb303acc992d75a360267aa3b5de7134d220411c852a6f17de7c0d0b8c8dcc0f567f67874c00f4528672b2a4f1bc978a3ada64c8c78467
+ languageName: node
+ linkType: hard
+
"@babel/helper-validator-identifier@npm:^7.18.6, @babel/helper-validator-identifier@npm:^7.19.1":
version: 7.19.1
resolution: "@babel/helper-validator-identifier@npm:7.19.1"
@@ -383,6 +447,13 @@ __metadata:
languageName: node
linkType: hard
+"@babel/helper-validator-identifier@npm:^7.22.20":
+ version: 7.22.20
+ resolution: "@babel/helper-validator-identifier@npm:7.22.20"
+ checksum: 136412784d9428266bcdd4d91c32bcf9ff0e8d25534a9d94b044f77fe76bc50f941a90319b05aafd1ec04f7d127cd57a179a3716009ff7f3412ef835ada95bdc
+ languageName: node
+ linkType: hard
+
"@babel/helper-validator-option@npm:^7.18.6, @babel/helper-validator-option@npm:^7.21.0":
version: 7.21.0
resolution: "@babel/helper-validator-option@npm:7.21.0"
@@ -424,6 +495,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/highlight@npm:^7.22.13":
+ version: 7.22.20
+ resolution: "@babel/highlight@npm:7.22.20"
+ dependencies:
+ "@babel/helper-validator-identifier": ^7.22.20
+ chalk: ^2.4.2
+ js-tokens: ^4.0.0
+ checksum: 84bd034dca309a5e680083cd827a766780ca63cef37308404f17653d32366ea76262bd2364b2d38776232f2d01b649f26721417d507e8b4b6da3e4e739f6d134
+ languageName: node
+ linkType: hard
+
"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.12.11, @babel/parser@npm:^7.12.7, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.21.3":
version: 7.21.3
resolution: "@babel/parser@npm:7.21.3"
@@ -433,6 +515,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.0":
+ version: 7.23.0
+ resolution: "@babel/parser@npm:7.23.0"
+ bin:
+ parser: ./bin/babel-parser.js
+ checksum: 453fdf8b9e2c2b7d7b02139e0ce003d1af21947bbc03eb350fb248ee335c9b85e4ab41697ddbdd97079698de825a265e45a0846bb2ed47a2c7c1df833f42a354
+ languageName: node
+ linkType: hard
+
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.18.6":
version: 7.18.6
resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.18.6"
@@ -1622,21 +1713,32 @@ __metadata:
languageName: node
linkType: hard
-"@babel/traverse@npm:^7.1.6, @babel/traverse@npm:^7.12.11, @babel/traverse@npm:^7.12.9, @babel/traverse@npm:^7.13.0, @babel/traverse@npm:^7.20.5, @babel/traverse@npm:^7.20.7, @babel/traverse@npm:^7.21.0, @babel/traverse@npm:^7.21.2, @babel/traverse@npm:^7.21.3, @babel/traverse@npm:^7.4.5, @babel/traverse@npm:^7.7.2":
- version: 7.21.3
- resolution: "@babel/traverse@npm:7.21.3"
+"@babel/template@npm:^7.22.15":
+ version: 7.22.15
+ resolution: "@babel/template@npm:7.22.15"
dependencies:
- "@babel/code-frame": ^7.18.6
- "@babel/generator": ^7.21.3
- "@babel/helper-environment-visitor": ^7.18.9
- "@babel/helper-function-name": ^7.21.0
- "@babel/helper-hoist-variables": ^7.18.6
- "@babel/helper-split-export-declaration": ^7.18.6
- "@babel/parser": ^7.21.3
- "@babel/types": ^7.21.3
+ "@babel/code-frame": ^7.22.13
+ "@babel/parser": ^7.22.15
+ "@babel/types": ^7.22.15
+ checksum: 1f3e7dcd6c44f5904c184b3f7fe280394b191f2fed819919ffa1e529c259d5b197da8981b6ca491c235aee8dbad4a50b7e31304aa531271cb823a4a24a0dd8fd
+ languageName: node
+ linkType: hard
+
+"@babel/traverse@npm:^7.1.6, @babel/traverse@npm:^7.12.11, @babel/traverse@npm:^7.12.9, @babel/traverse@npm:^7.13.0, @babel/traverse@npm:^7.20.5, @babel/traverse@npm:^7.20.7, @babel/traverse@npm:^7.21.0, @babel/traverse@npm:^7.21.2, @babel/traverse@npm:^7.21.3, @babel/traverse@npm:^7.4.5, @babel/traverse@npm:^7.7.2":
+ version: 7.23.2
+ resolution: "@babel/traverse@npm:7.23.2"
+ dependencies:
+ "@babel/code-frame": ^7.22.13
+ "@babel/generator": ^7.23.0
+ "@babel/helper-environment-visitor": ^7.22.20
+ "@babel/helper-function-name": ^7.23.0
+ "@babel/helper-hoist-variables": ^7.22.5
+ "@babel/helper-split-export-declaration": ^7.22.6
+ "@babel/parser": ^7.23.0
+ "@babel/types": ^7.23.0
debug: ^4.1.0
globals: ^11.1.0
- checksum: 0af5bcd47a2fc501592b90ac1feae9d449afb9ab0772a4f6e68230f4cd3a475795d538c1de3f880fe3414b6c2820bac84d02c6549eea796f39d74a603717447b
+ checksum: 26a1eea0dde41ab99dde8b9773a013a0dc50324e5110a049f5d634e721ff08afffd54940b3974a20308d7952085ac769689369e9127dea655f868c0f6e1ab35d
languageName: node
linkType: hard
@@ -1651,6 +1753,17 @@ __metadata:
languageName: node
linkType: hard
+"@babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0":
+ version: 7.23.0
+ resolution: "@babel/types@npm:7.23.0"
+ dependencies:
+ "@babel/helper-string-parser": ^7.22.5
+ "@babel/helper-validator-identifier": ^7.22.20
+ to-fast-properties: ^2.0.0
+ checksum: 215fe04bd7feef79eeb4d33374b39909ce9cad1611c4135a4f7fdf41fe3280594105af6d7094354751514625ea92d0875aba355f53e86a92600f290e77b0e604
+ languageName: node
+ linkType: hard
+
"@babel/types@npm:^7.8.3":
version: 7.21.4
resolution: "@babel/types@npm:7.21.4"
@@ -1921,14 +2034,14 @@ __metadata:
"@consensys/starknet-snap@file:../starknet-snap::locator=wallet-ui%40workspace%3Apackages%2Fwallet-ui":
version: 2.2.0
- resolution: "@consensys/starknet-snap@file:../starknet-snap#../starknet-snap::hash=f33260&locator=wallet-ui%40workspace%3Apackages%2Fwallet-ui"
+ resolution: "@consensys/starknet-snap@file:../starknet-snap#../starknet-snap::hash=09b51d&locator=wallet-ui%40workspace%3Apackages%2Fwallet-ui"
dependencies:
async-mutex: ^0.3.2
ethereum-unit-converter: ^0.0.17
ethers: ^5.5.1
starknet: ^5.14.0
starknet_v4.22.0: "npm:starknet@4.22.0"
- checksum: 6457a8423d6468621a5550c2235517929c6d23012b1574ed6655a5224cdd9bf50328279079fdd66cc2b4fcdd3a017314a4429758a9051249fc2780800536d8f8
+ checksum: fee364b7c342fedbbeda32f0d35fc90a826ad42d2948e329f5893ab03e25536b57dd15a342428bda8e628a4416f01dc0102d63450056f0a4799e700279d34fec
languageName: node
linkType: hard
@@ -3374,6 +3487,16 @@ __metadata:
languageName: node
linkType: hard
+"@jridgewell/source-map@npm:^0.3.3":
+ version: 0.3.5
+ resolution: "@jridgewell/source-map@npm:0.3.5"
+ dependencies:
+ "@jridgewell/gen-mapping": ^0.3.0
+ "@jridgewell/trace-mapping": ^0.3.9
+ checksum: 1ad4dec0bdafbade57920a50acec6634f88a0eb735851e0dda906fa9894e7f0549c492678aad1a10f8e144bfe87f238307bf2a914a1bc85b7781d345417e9f6f
+ languageName: node
+ linkType: hard
+
"@jridgewell/sourcemap-codec@npm:1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.10":
version: 1.4.14
resolution: "@jridgewell/sourcemap-codec@npm:1.4.14"
@@ -6104,6 +6227,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/estree@npm:^1.0.0":
+ version: 1.0.4
+ resolution: "@types/estree@npm:1.0.4"
+ checksum: dcd08e6e967def3afff745774b6b9b912d6394ddacbb3e8be05bb291c1803f5f03f1ab0eeb852bf8a85ca14842663f461f3dac82179dcdccbf45fbc067673bbc
+ languageName: node
+ linkType: hard
+
"@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.33":
version: 4.17.33
resolution: "@types/express-serve-static-core@npm:4.17.33"
@@ -6860,6 +6990,16 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/ast@npm:1.11.6, @webassemblyjs/ast@npm:^1.11.5":
+ version: 1.11.6
+ resolution: "@webassemblyjs/ast@npm:1.11.6"
+ dependencies:
+ "@webassemblyjs/helper-numbers": 1.11.6
+ "@webassemblyjs/helper-wasm-bytecode": 1.11.6
+ checksum: 38ef1b526ca47c210f30975b06df2faf1a8170b1636ce239fc5738fc231ce28389dd61ecedd1bacfc03cbe95b16d1af848c805652080cb60982836eb4ed2c6cf
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/ast@npm:1.9.0":
version: 1.9.0
resolution: "@webassemblyjs/ast@npm:1.9.0"
@@ -6878,6 +7018,13 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/floating-point-hex-parser@npm:1.11.6":
+ version: 1.11.6
+ resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.11.6"
+ checksum: 29b08758841fd8b299c7152eda36b9eb4921e9c584eb4594437b5cd90ed6b920523606eae7316175f89c20628da14326801090167cc7fbffc77af448ac84b7e2
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/floating-point-hex-parser@npm:1.9.0":
version: 1.9.0
resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.9.0"
@@ -6892,6 +7039,13 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/helper-api-error@npm:1.11.6":
+ version: 1.11.6
+ resolution: "@webassemblyjs/helper-api-error@npm:1.11.6"
+ checksum: e8563df85161096343008f9161adb138a6e8f3c2cc338d6a36011aa55eabb32f2fd138ffe63bc278d009ada001cc41d263dadd1c0be01be6c2ed99076103689f
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/helper-api-error@npm:1.9.0":
version: 1.9.0
resolution: "@webassemblyjs/helper-api-error@npm:1.9.0"
@@ -6906,6 +7060,13 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/helper-buffer@npm:1.11.6":
+ version: 1.11.6
+ resolution: "@webassemblyjs/helper-buffer@npm:1.11.6"
+ checksum: b14d0573bf680d22b2522e8a341ec451fddd645d1f9c6bd9012ccb7e587a2973b86ab7b89fe91e1c79939ba96095f503af04369a3b356c8023c13a5893221644
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/helper-buffer@npm:1.9.0":
version: 1.9.0
resolution: "@webassemblyjs/helper-buffer@npm:1.9.0"
@@ -6949,6 +7110,17 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/helper-numbers@npm:1.11.6":
+ version: 1.11.6
+ resolution: "@webassemblyjs/helper-numbers@npm:1.11.6"
+ dependencies:
+ "@webassemblyjs/floating-point-hex-parser": 1.11.6
+ "@webassemblyjs/helper-api-error": 1.11.6
+ "@xtuc/long": 4.2.2
+ checksum: f4b562fa219f84368528339e0f8d273ad44e047a07641ffcaaec6f93e5b76fd86490a009aa91a294584e1436d74b0a01fa9fde45e333a4c657b58168b04da424
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/helper-wasm-bytecode@npm:1.11.1":
version: 1.11.1
resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.11.1"
@@ -6956,6 +7128,13 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/helper-wasm-bytecode@npm:1.11.6":
+ version: 1.11.6
+ resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.11.6"
+ checksum: 3535ef4f1fba38de3475e383b3980f4bbf3de72bbb631c2b6584c7df45be4eccd62c6ff48b5edd3f1bcff275cfd605a37679ec199fc91fd0a7705d7f1e3972dc
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/helper-wasm-bytecode@npm:1.9.0":
version: 1.9.0
resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.9.0"
@@ -6975,6 +7154,18 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/helper-wasm-section@npm:1.11.6":
+ version: 1.11.6
+ resolution: "@webassemblyjs/helper-wasm-section@npm:1.11.6"
+ dependencies:
+ "@webassemblyjs/ast": 1.11.6
+ "@webassemblyjs/helper-buffer": 1.11.6
+ "@webassemblyjs/helper-wasm-bytecode": 1.11.6
+ "@webassemblyjs/wasm-gen": 1.11.6
+ checksum: b2cf751bf4552b5b9999d27bbb7692d0aca75260140195cb58ea6374d7b9c2dc69b61e10b211a0e773f66209c3ddd612137ed66097e3684d7816f854997682e9
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/helper-wasm-section@npm:1.9.0":
version: 1.9.0
resolution: "@webassemblyjs/helper-wasm-section@npm:1.9.0"
@@ -6996,6 +7187,15 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/ieee754@npm:1.11.6":
+ version: 1.11.6
+ resolution: "@webassemblyjs/ieee754@npm:1.11.6"
+ dependencies:
+ "@xtuc/ieee754": ^1.2.0
+ checksum: 13574b8e41f6ca39b700e292d7edf102577db5650fe8add7066a320aa4b7a7c09a5056feccac7a74eb68c10dea9546d4461412af351f13f6b24b5f32379b49de
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/ieee754@npm:1.9.0":
version: 1.9.0
resolution: "@webassemblyjs/ieee754@npm:1.9.0"
@@ -7014,6 +7214,15 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/leb128@npm:1.11.6":
+ version: 1.11.6
+ resolution: "@webassemblyjs/leb128@npm:1.11.6"
+ dependencies:
+ "@xtuc/long": 4.2.2
+ checksum: 7ea942dc9777d4b18a5ebfa3a937b30ae9e1d2ce1fee637583ed7f376334dd1d4274f813d2e250056cca803e0952def4b954913f1a3c9068bcd4ab4ee5143bf0
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/leb128@npm:1.9.0":
version: 1.9.0
resolution: "@webassemblyjs/leb128@npm:1.9.0"
@@ -7030,6 +7239,13 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/utf8@npm:1.11.6":
+ version: 1.11.6
+ resolution: "@webassemblyjs/utf8@npm:1.11.6"
+ checksum: 807fe5b5ce10c390cfdd93e0fb92abda8aebabb5199980681e7c3743ee3306a75729bcd1e56a3903980e96c885ee53ef901fcbaac8efdfa480f9c0dae1d08713
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/utf8@npm:1.9.0":
version: 1.9.0
resolution: "@webassemblyjs/utf8@npm:1.9.0"
@@ -7069,6 +7285,22 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/wasm-edit@npm:^1.11.5":
+ version: 1.11.6
+ resolution: "@webassemblyjs/wasm-edit@npm:1.11.6"
+ dependencies:
+ "@webassemblyjs/ast": 1.11.6
+ "@webassemblyjs/helper-buffer": 1.11.6
+ "@webassemblyjs/helper-wasm-bytecode": 1.11.6
+ "@webassemblyjs/helper-wasm-section": 1.11.6
+ "@webassemblyjs/wasm-gen": 1.11.6
+ "@webassemblyjs/wasm-opt": 1.11.6
+ "@webassemblyjs/wasm-parser": 1.11.6
+ "@webassemblyjs/wast-printer": 1.11.6
+ checksum: 29ce75870496d6fad864d815ebb072395a8a3a04dc9c3f4e1ffdc63fc5fa58b1f34304a1117296d8240054cfdbc38aca88e71fb51483cf29ffab0a61ef27b481
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/wasm-gen@npm:1.11.1":
version: 1.11.1
resolution: "@webassemblyjs/wasm-gen@npm:1.11.1"
@@ -7082,6 +7314,19 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/wasm-gen@npm:1.11.6":
+ version: 1.11.6
+ resolution: "@webassemblyjs/wasm-gen@npm:1.11.6"
+ dependencies:
+ "@webassemblyjs/ast": 1.11.6
+ "@webassemblyjs/helper-wasm-bytecode": 1.11.6
+ "@webassemblyjs/ieee754": 1.11.6
+ "@webassemblyjs/leb128": 1.11.6
+ "@webassemblyjs/utf8": 1.11.6
+ checksum: a645a2eecbea24833c3260a249704a7f554ef4a94c6000984728e94bb2bc9140a68dfd6fd21d5e0bbb09f6dfc98e083a45760a83ae0417b41a0196ff6d45a23a
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/wasm-gen@npm:1.9.0":
version: 1.9.0
resolution: "@webassemblyjs/wasm-gen@npm:1.9.0"
@@ -7107,6 +7352,18 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/wasm-opt@npm:1.11.6":
+ version: 1.11.6
+ resolution: "@webassemblyjs/wasm-opt@npm:1.11.6"
+ dependencies:
+ "@webassemblyjs/ast": 1.11.6
+ "@webassemblyjs/helper-buffer": 1.11.6
+ "@webassemblyjs/wasm-gen": 1.11.6
+ "@webassemblyjs/wasm-parser": 1.11.6
+ checksum: b4557f195487f8e97336ddf79f7bef40d788239169aac707f6eaa2fa5fe243557c2d74e550a8e57f2788e70c7ae4e7d32f7be16101afe183d597b747a3bdd528
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/wasm-opt@npm:1.9.0":
version: 1.9.0
resolution: "@webassemblyjs/wasm-opt@npm:1.9.0"
@@ -7133,6 +7390,20 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/wasm-parser@npm:1.11.6, @webassemblyjs/wasm-parser@npm:^1.11.5":
+ version: 1.11.6
+ resolution: "@webassemblyjs/wasm-parser@npm:1.11.6"
+ dependencies:
+ "@webassemblyjs/ast": 1.11.6
+ "@webassemblyjs/helper-api-error": 1.11.6
+ "@webassemblyjs/helper-wasm-bytecode": 1.11.6
+ "@webassemblyjs/ieee754": 1.11.6
+ "@webassemblyjs/leb128": 1.11.6
+ "@webassemblyjs/utf8": 1.11.6
+ checksum: 8200a8d77c15621724a23fdabe58d5571415cda98a7058f542e670ea965dd75499f5e34a48675184947c66f3df23adf55df060312e6d72d57908e3f049620d8a
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/wasm-parser@npm:1.9.0":
version: 1.9.0
resolution: "@webassemblyjs/wasm-parser@npm:1.9.0"
@@ -7171,6 +7442,16 @@ __metadata:
languageName: node
linkType: hard
+"@webassemblyjs/wast-printer@npm:1.11.6":
+ version: 1.11.6
+ resolution: "@webassemblyjs/wast-printer@npm:1.11.6"
+ dependencies:
+ "@webassemblyjs/ast": 1.11.6
+ "@xtuc/long": 4.2.2
+ checksum: d2fa6a4c427325ec81463e9c809aa6572af6d47f619f3091bf4c4a6fc34f1da3df7caddaac50b8e7a457f8784c62cd58c6311b6cb69b0162ccd8d4c072f79cf8
+ languageName: node
+ linkType: hard
+
"@webassemblyjs/wast-printer@npm:1.9.0":
version: 1.9.0
resolution: "@webassemblyjs/wast-printer@npm:1.9.0"
@@ -7251,6 +7532,15 @@ __metadata:
languageName: node
linkType: hard
+"acorn-import-assertions@npm:^1.9.0":
+ version: 1.9.0
+ resolution: "acorn-import-assertions@npm:1.9.0"
+ peerDependencies:
+ acorn: ^8
+ checksum: 944fb2659d0845c467066bdcda2e20c05abe3aaf11972116df457ce2627628a81764d800dd55031ba19de513ee0d43bb771bc679cc0eda66dc8b4fade143bc0c
+ languageName: node
+ linkType: hard
+
"acorn-jsx@npm:^5.3.1, acorn-jsx@npm:^5.3.2":
version: 5.3.2
resolution: "acorn-jsx@npm:5.3.2"
@@ -7312,6 +7602,15 @@ __metadata:
languageName: node
linkType: hard
+"acorn@npm:^8.8.2":
+ version: 8.11.2
+ resolution: "acorn@npm:8.11.2"
+ bin:
+ acorn: bin/acorn
+ checksum: 818450408684da89423e3daae24e4dc9b68692db8ab49ea4569c7c5abb7a3f23669438bf129cc81dfdada95e1c9b944ee1bfca2c57a05a4dc73834a612fbf6a7
+ languageName: node
+ linkType: hard
+
"add-stream@npm:^1.0.0":
version: 1.0.0
resolution: "add-stream@npm:1.0.0"
@@ -8516,7 +8815,7 @@ __metadata:
languageName: node
linkType: hard
-"bn.js@npm:^5.0.0, bn.js@npm:^5.1.1, bn.js@npm:^5.1.2, bn.js@npm:^5.2.0, bn.js@npm:^5.2.1":
+"bn.js@npm:^5.0.0, bn.js@npm:^5.1.2, bn.js@npm:^5.2.0, bn.js@npm:^5.2.1":
version: 5.2.1
resolution: "bn.js@npm:5.2.1"
checksum: 3dd8c8d38055fedfa95c1d5fc3c99f8dd547b36287b37768db0abab3c239711f88ff58d18d155dd8ad902b0b0cee973747b7ae20ea12a09473272b0201c9edd3
@@ -8723,7 +9022,7 @@ __metadata:
languageName: node
linkType: hard
-"browserify-rsa@npm:^4.0.0, browserify-rsa@npm:^4.0.1":
+"browserify-rsa@npm:^4.0.0, browserify-rsa@npm:^4.1.0":
version: 4.1.0
resolution: "browserify-rsa@npm:4.1.0"
dependencies:
@@ -8734,19 +9033,19 @@ __metadata:
linkType: hard
"browserify-sign@npm:^4.0.0":
- version: 4.2.1
- resolution: "browserify-sign@npm:4.2.1"
+ version: 4.2.2
+ resolution: "browserify-sign@npm:4.2.2"
dependencies:
- bn.js: ^5.1.1
- browserify-rsa: ^4.0.1
+ bn.js: ^5.2.1
+ browserify-rsa: ^4.1.0
create-hash: ^1.2.0
create-hmac: ^1.1.7
- elliptic: ^6.5.3
+ elliptic: ^6.5.4
inherits: ^2.0.4
- parse-asn1: ^5.1.5
- readable-stream: ^3.6.0
- safe-buffer: ^5.2.0
- checksum: 0221f190e3f5b2d40183fa51621be7e838d9caa329fe1ba773406b7637855f37b30f5d83e52ff8f244ed12ffe6278dd9983638609ed88c841ce547e603855707
+ parse-asn1: ^5.1.6
+ readable-stream: ^3.6.2
+ safe-buffer: ^5.2.1
+ checksum: b622730c0fc183328c3a1c9fdaaaa5118821ed6822b266fa6b0375db7e20061ebec87301d61931d79b9da9a96ada1cab317fce3c68f233e5e93ed02dbb35544c
languageName: node
linkType: hard
@@ -11615,6 +11914,16 @@ __metadata:
languageName: node
linkType: hard
+"enhanced-resolve@npm:^5.15.0":
+ version: 5.15.0
+ resolution: "enhanced-resolve@npm:5.15.0"
+ dependencies:
+ graceful-fs: ^4.2.4
+ tapable: ^2.2.0
+ checksum: fbd8cdc9263be71cc737aa8a7d6c57b43d6aa38f6cc75dde6fcd3598a130cc465f979d2f4d01bb3bf475acb43817749c79f8eef9be048683602ca91ab52e4f11
+ languageName: node
+ linkType: hard
+
"entities@npm:^2.0.0":
version: 2.2.0
resolution: "entities@npm:2.2.0"
@@ -11738,6 +12047,13 @@ __metadata:
languageName: node
linkType: hard
+"es-module-lexer@npm:^1.2.1":
+ version: 1.3.1
+ resolution: "es-module-lexer@npm:1.3.1"
+ checksum: 3beafa7e171eb1e8cc45695edf8d51638488dddf65294d7911f8d6a96249da6a9838c87529262cc6ea53988d8272cec0f4bff93f476ed031a54ba3afb51a0ed3
+ languageName: node
+ linkType: hard
+
"es-set-tostringtag@npm:^2.0.1":
version: 2.0.1
resolution: "es-set-tostringtag@npm:2.0.1"
@@ -18616,7 +18932,7 @@ __metadata:
languageName: node
linkType: hard
-"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.5":
+"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.6":
version: 5.1.6
resolution: "parse-asn1@npm:5.1.6"
dependencies:
@@ -20822,7 +21138,7 @@ __metadata:
languageName: node
linkType: hard
-"readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.2, readable-stream@npm:^3.0.6, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0":
+"readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.2, readable-stream@npm:^3.0.6, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0, readable-stream@npm:^3.6.2":
version: 3.6.2
resolution: "readable-stream@npm:3.6.2"
dependencies:
@@ -21482,7 +21798,7 @@ __metadata:
languageName: node
linkType: hard
-"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.0, safe-buffer@npm:~5.2.0":
+"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.0, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0":
version: 5.2.1
resolution: "safe-buffer@npm:5.2.1"
checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491
@@ -21636,6 +21952,17 @@ __metadata:
languageName: node
linkType: hard
+"schema-utils@npm:^3.2.0":
+ version: 3.3.0
+ resolution: "schema-utils@npm:3.3.0"
+ dependencies:
+ "@types/json-schema": ^7.0.8
+ ajv: ^6.12.5
+ ajv-keywords: ^3.5.2
+ checksum: ea56971926fac2487f0757da939a871388891bc87c6a82220d125d587b388f1704788f3706e7f63a7b70e49fc2db974c41343528caea60444afd5ce0fe4b85c0
+ languageName: node
+ linkType: hard
+
"schema-utils@npm:^4.0.0":
version: 4.0.0
resolution: "schema-utils@npm:4.0.0"
@@ -23254,6 +23581,28 @@ __metadata:
languageName: node
linkType: hard
+"terser-webpack-plugin@npm:^5.3.7":
+ version: 5.3.9
+ resolution: "terser-webpack-plugin@npm:5.3.9"
+ dependencies:
+ "@jridgewell/trace-mapping": ^0.3.17
+ jest-worker: ^27.4.5
+ schema-utils: ^3.1.1
+ serialize-javascript: ^6.0.1
+ terser: ^5.16.8
+ peerDependencies:
+ webpack: ^5.1.0
+ peerDependenciesMeta:
+ "@swc/core":
+ optional: true
+ esbuild:
+ optional: true
+ uglify-js:
+ optional: true
+ checksum: 41705713d6f9cb83287936b21e27c658891c78c4392159f5148b5623f0e8c48559869779619b058382a4c9758e7820ea034695e57dc7c474b4962b79f553bc5f
+ languageName: node
+ linkType: hard
+
"terser@npm:^4.1.2, terser@npm:^4.6.3":
version: 4.8.1
resolution: "terser@npm:4.8.1"
@@ -23281,6 +23630,20 @@ __metadata:
languageName: node
linkType: hard
+"terser@npm:^5.16.8":
+ version: 5.24.0
+ resolution: "terser@npm:5.24.0"
+ dependencies:
+ "@jridgewell/source-map": ^0.3.3
+ acorn: ^8.8.2
+ commander: ^2.20.0
+ source-map-support: ~0.5.20
+ bin:
+ terser: bin/terser
+ checksum: d88f774b6fa711a234fcecefd7657f99189c367e17dbe95a51c2776d426ad0e4d98d1ffe6edfdf299877c7602e495bdd711d21b2caaec188410795e5447d0f6c
+ languageName: node
+ linkType: hard
+
"test-exclude@npm:^6.0.0":
version: 6.0.0
resolution: "test-exclude@npm:6.0.0"
@@ -24464,7 +24827,7 @@ __metadata:
toastr2: ^3.0.0-alpha.18
typescript: ^4.7.4
web-vitals: ^2.1.4
- webpack: 5
+ webpack: ^5.76.0
languageName: unknown
linkType: soft
@@ -24803,7 +25166,7 @@ __metadata:
languageName: node
linkType: hard
-"webpack@npm:5, webpack@npm:>=4.43.0 <6.0.0, webpack@npm:^5.64.4, webpack@npm:^5.9.0":
+"webpack@npm:>=4.43.0 <6.0.0, webpack@npm:^5.64.4, webpack@npm:^5.9.0":
version: 5.76.1
resolution: "webpack@npm:5.76.1"
dependencies:
@@ -24840,6 +25203,43 @@ __metadata:
languageName: node
linkType: hard
+"webpack@npm:^5.76.0":
+ version: 5.89.0
+ resolution: "webpack@npm:5.89.0"
+ dependencies:
+ "@types/eslint-scope": ^3.7.3
+ "@types/estree": ^1.0.0
+ "@webassemblyjs/ast": ^1.11.5
+ "@webassemblyjs/wasm-edit": ^1.11.5
+ "@webassemblyjs/wasm-parser": ^1.11.5
+ acorn: ^8.7.1
+ acorn-import-assertions: ^1.9.0
+ browserslist: ^4.14.5
+ chrome-trace-event: ^1.0.2
+ enhanced-resolve: ^5.15.0
+ es-module-lexer: ^1.2.1
+ eslint-scope: 5.1.1
+ events: ^3.2.0
+ glob-to-regexp: ^0.4.1
+ graceful-fs: ^4.2.9
+ json-parse-even-better-errors: ^2.3.1
+ loader-runner: ^4.2.0
+ mime-types: ^2.1.27
+ neo-async: ^2.6.2
+ schema-utils: ^3.2.0
+ tapable: ^2.1.1
+ terser-webpack-plugin: ^5.3.7
+ watchpack: ^2.4.0
+ webpack-sources: ^3.2.3
+ peerDependenciesMeta:
+ webpack-cli:
+ optional: true
+ bin:
+ webpack: bin/webpack.js
+ checksum: 43fe0dbc30e168a685ef5a86759d5016a705f6563b39a240aa00826a80637d4a3deeb8062e709d6a4b05c63e796278244c84b04174704dc4a37bedb0f565c5ed
+ languageName: node
+ linkType: hard
+
"websocket-driver@npm:>=0.5.1, websocket-driver@npm:^0.7.4":
version: 0.7.4
resolution: "websocket-driver@npm:0.7.4"