Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 2.3.0 release cario 1 upgrade #177

Closed
wants to merge 12 commits into from
Closed
2 changes: 1 addition & 1 deletion packages/starknet-snap/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/ConsenSys/starknet-snap.git"
},
"source": {
"shasum": "CmWnKZgn0YwhCONy9eAp6caU/4MFPO74bXReg/IlBPw=",
"shasum": "yqSLTJy0WyWa+iX4Yx61DMnY7hrA8BdnBJwNEOAy2I8=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
26 changes: 8 additions & 18 deletions packages/starknet-snap/src/createAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import {
getKeysFromAddressIndex,
getAccContractAddressAndCallData,
deployAccount,
callContract,
getBalance,
estimateAccountDeployFee,
getSigner,
isAccountDeployed,
} from './utils/starknetUtils';
import {
getEtherErc20Token,
Expand Down Expand Up @@ -45,8 +45,6 @@ export async function createAccount(params: ApiParams, silentMode = false) {

let failureReason = '';
let estimateDeployFee: EstimateFee;
let signerAssigned = true;
let signer = '';

if (deploy) {
if (!silentMode) {
Expand All @@ -72,24 +70,16 @@ export async function createAccount(params: ApiParams, silentMode = false) {
};
}

try {
signer = await getSigner(contractAddress, network);
logger.log(`createAccount:\ngetSigner: contractAddress = ${contractAddress}, signerPublicKey= ${signer}`);
failureReason = 'The account address had already been deployed';
} catch (err) {
signerAssigned = false;
logger.log(`createAccount:\ngetSigner: err in get signer: ${toJson(err)}`);
}
const signerAssigned = await isAccountDeployed(network, contractAddress);

if (!signerAssigned) {
try {
const getBalanceResp = await callContract(
network,
const balance = await getBalance(
getEtherErc20Token(state, network.chainId)?.address,
'balanceOf',
[num.toBigInt(contractAddress).toString(10)],
num.toBigInt(contractAddress).toString(10),
network,
);
logger.log(`createAccount:\ngetBalanceResp: ${toJson(getBalanceResp)}`);
logger.log(`createAccount:\ngetBalanceResp: ${balance}`);
estimateDeployFee = await estimateAccountDeployFee(
network,
contractAddress,
Expand All @@ -98,7 +88,7 @@ export async function createAccount(params: ApiParams, silentMode = false) {
privateKey,
);
logger.log(`createAccount:\nestimateDeployFee: ${toJson(estimateDeployFee)}`);
if (Number(getBalanceResp.result[0]) < Number(estimateDeployFee.suggestedMaxFee)) {
if (Number(balance) < Number(estimateDeployFee.suggestedMaxFee)) {
const gasFeeStr = ethers.utils.formatUnits(estimateDeployFee.suggestedMaxFee.toString(10), 18);
const gasFeeFloat = parseFloat(gasFeeStr).toFixed(6); // 6 decimal places for ether
const gasFeeInEther = Number(gasFeeFloat) === 0 ? '0.000001' : gasFeeFloat;
Expand Down
32 changes: 18 additions & 14 deletions packages/starknet-snap/src/estimateFee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,22 @@ import {
estimateFeeBulk,
addFeesFromAllTransactions,
isAccountDeployed,
isUpgradeRequired,
} from './utils/starknetUtils';

import { PROXY_CONTRACT_HASH } from './utils/constants';
import { ACCOUNT_CLASS_HASH_V1 } from './utils/constants';
import { logger } from './utils/logger';

export async function estimateFee(params: ApiParams) {
try {
const { state, keyDeriver, requestParams } = params;
const requestParamsObj = requestParams as EstimateFeeRequestParams;
const contractAddress = requestParamsObj.contractAddress;
const contractFuncName = requestParamsObj.contractFuncName;
const contractCallData = getCallDataArray(requestParamsObj.contractCallData);
const senderAddress = requestParamsObj.senderAddress;
const network = getNetworkFromChainId(state, requestParamsObj.chainId);

if (!requestParamsObj.contractAddress || !requestParamsObj.senderAddress || !requestParamsObj.contractFuncName) {
if (!contractAddress || !requestParamsObj.senderAddress || !contractFuncName) {
throw new Error(
`The given contract address, sender address, and function name need to be non-empty string, got: ${toJson(
requestParamsObj,
Expand All @@ -30,21 +35,20 @@ export async function estimateFee(params: ApiParams) {
}

try {
validateAndParseAddress(requestParamsObj.contractAddress);
validateAndParseAddress(contractAddress);
} catch (err) {
throw new Error(`The given contract address is invalid: ${requestParamsObj.contractAddress}`);
throw new Error(`The given contract address is invalid: ${contractAddress}`);
}
try {
validateAndParseAddress(requestParamsObj.senderAddress);
validateAndParseAddress(senderAddress);
} catch (err) {
throw new Error(`The given sender address is invalid: ${requestParamsObj.senderAddress}`);
throw new Error(`The given sender address is invalid: ${senderAddress}`);
}

if (await isUpgradeRequired(network, senderAddress)) {
throw new Error('Upgrade required');
}

const contractAddress = requestParamsObj.contractAddress;
const contractFuncName = requestParamsObj.contractFuncName;
const contractCallData = getCallDataArray(requestParamsObj.contractCallData);
const senderAddress = requestParamsObj.senderAddress;
const network = getNetworkFromChainId(state, requestParamsObj.chainId);
const { privateKey: senderPrivateKey, publicKey } = await getKeysFromAddress(
keyDeriver,
network,
Expand All @@ -61,7 +65,7 @@ export async function estimateFee(params: ApiParams) {
logger.log(`estimateFee:\ntxnInvocation: ${toJson(txnInvocation)}`);

//Estimate deploy account fee if the signer has not been deployed yet
const accountDeployed = await isAccountDeployed(network, publicKey);
const accountDeployed = await isAccountDeployed(network, senderAddress);
let bulkTransactions: Invocations = [
{
type: TransactionType.INVOKE,
Expand All @@ -71,7 +75,7 @@ export async function estimateFee(params: ApiParams) {
if (!accountDeployed) {
const { callData } = getAccContractAddressAndCallData(publicKey);
const deployAccountpayload = {
classHash: PROXY_CONTRACT_HASH,
classHash: ACCOUNT_CLASS_HASH_V1,
contractAddress: senderAddress,
constructorCalldata: callData,
addressSalt: publicKey,
Expand Down
21 changes: 11 additions & 10 deletions packages/starknet-snap/src/extractPrivateKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { toJson } from './utils/serializer';
import { validateAndParseAddress } from '../src/utils/starknetUtils';
import { ApiParams, ExtractPrivateKeyRequestParams } from './types/snapApi';
import { getNetworkFromChainId } from './utils/snapUtils';
import { getKeysFromAddress } from './utils/starknetUtils';
import { getKeysFromAddress, isUpgradeRequired } from './utils/starknetUtils';
import { DialogType } from '@metamask/rpc-methods';
import { copyable, panel, text } from '@metamask/snaps-ui';
import { logger } from './utils/logger';
Expand All @@ -11,17 +11,20 @@ export async function extractPrivateKey(params: ApiParams) {
try {
const { state, wallet, keyDeriver, requestParams } = params;
const requestParamsObj = requestParams as ExtractPrivateKeyRequestParams;

if (!requestParamsObj.userAddress) {
throw new Error(
`The given user address need to be non-empty string, got: ${toJson(requestParamsObj.userAddress)}`,
);
const network = getNetworkFromChainId(state, requestParamsObj.chainId);
const userAddress = requestParamsObj.userAddress;
if (!userAddress) {
throw new Error(`The given user address need to be non-empty string, got: ${toJson(userAddress)}`);
}

try {
validateAndParseAddress(requestParamsObj.userAddress);
validateAndParseAddress(userAddress);
} catch (err) {
throw new Error(`The given user address is invalid: ${requestParamsObj.userAddress}`);
throw new Error(`The given user address is invalid: ${userAddress}`);
}

if (await isUpgradeRequired(network, userAddress)) {
throw new Error('Upgrade required');
}

const response = await wallet.request({
Expand All @@ -33,8 +36,6 @@ export async function extractPrivateKey(params: ApiParams) {
});

if (response === true) {
const userAddress = requestParamsObj.userAddress;
const network = getNetworkFromChainId(state, requestParamsObj.chainId);
const { privateKey: userPrivateKey } = await getKeysFromAddress(keyDeriver, network, state, userAddress);

await wallet.request({
Expand Down
6 changes: 5 additions & 1 deletion packages/starknet-snap/src/extractPublicKey.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { toJson } from './utils/serializer';
import { constants, num } from 'starknet';
import { validateAndParseAddress } from '../src/utils/starknetUtils';
import { validateAndParseAddress, isUpgradeRequired } from '../src/utils/starknetUtils';
import { ApiParams, ExtractPublicKeyRequestParams } from './types/snapApi';
import { getAccount, getNetworkFromChainId } from './utils/snapUtils';
import { getKeysFromAddress } from './utils/starknetUtils';
Expand All @@ -26,6 +26,10 @@ export async function extractPublicKey(params: ApiParams) {
throw new Error(`The given user address is invalid: ${requestParamsObj.userAddress}`);
}

if (await isUpgradeRequired(network, userAddress)) {
throw new Error('Upgrade required');
}

let userPublicKey;
const accContract = getAccount(state, userAddress, network.chainId);
if (!accContract?.publicKey || num.toBigInt(accContract.publicKey) === constants.ZERO) {
Expand Down
23 changes: 11 additions & 12 deletions packages/starknet-snap/src/recoverAccounts.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { toJson } from './utils/serializer';
import { num } from 'starknet';
import { getSigner, getKeysFromAddressIndex, getAccContractAddressAndCallData } from './utils/starknetUtils';
import { getKeysFromAddressIndex, getCorrectContractAddress, isUpgradeRequired } from './utils/starknetUtils';
import { getNetworkFromChainId, getValidNumber, upsertAccount } from './utils/snapUtils';
import { AccContract } from './types/snapState';
import { ApiParams, RecoverAccountsRequestParams } from './types/snapApi';
Expand Down Expand Up @@ -29,20 +29,18 @@ export async function recoverAccounts(params: ApiParams) {
state,
i,
);
const { address: contractAddress } = getAccContractAddressAndCallData(publicKey);
const { address: contractAddress, signerPubKey: signerPublicKey } = await getCorrectContractAddress(
network,
publicKey,
);
logger.log(`recoverAccounts: index ${i}:\ncontractAddress = ${contractAddress}\npublicKey = ${publicKey}`);

let signerPublicKey = '';

try {
signerPublicKey = await getSigner(contractAddress, network);
logger.log(`recoverAccounts: index ${i}\nsignerPublicKey: ${signerPublicKey}`);
} catch (err) {
logger.log(`recoverAccounts: index ${i}\nerr in get signer: ${toJson(err)}`);
signerPublicKey = '';
}

let _isUpgradeRequired = false;
if (signerPublicKey) {
_isUpgradeRequired = await isUpgradeRequired(network, contractAddress);
logger.log(
`recoverAccounts: index ${i}:\ncontractAddress = ${contractAddress}\nisUpgradeRequired = ${_isUpgradeRequired}`,
);
if (num.toBigInt(signerPublicKey) === num.toBigInt(publicKey)) {
logger.log(`recoverAccounts: index ${i} matched\npublicKey: ${publicKey}`);
}
Expand All @@ -59,6 +57,7 @@ export async function recoverAccounts(params: ApiParams) {
derivationPath,
deployTxnHash: '',
chainId: network.chainId,
upgradeRequired: _isUpgradeRequired,
};

logger.log(`recoverAccounts: index ${i}\nuserAccount: ${toJson(userAccount)}`);
Expand Down
29 changes: 21 additions & 8 deletions packages/starknet-snap/src/sendTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import { validateAndParseAddress } from '../src/utils/starknetUtils';
import { estimateFee } from './estimateFee';
import { Transaction, TransactionStatus, VoyagerTransactionType } from './types/snapState';
import { getNetworkFromChainId, getSendTxnText, upsertTransaction } from './utils/snapUtils';
import { getKeysFromAddress, getCallDataArray, executeTxn, isAccountDeployed } from './utils/starknetUtils';
import {
getKeysFromAddress,
getCallDataArray,
executeTxn,
isAccountDeployed,
isUpgradeRequired,
} from './utils/starknetUtils';
import { ApiParams, SendTransactionRequestParams } from './types/snapApi';
import { createAccount } from './createAccount';
import { DialogType } from '@metamask/rpc-methods';
Expand Down Expand Up @@ -40,11 +46,17 @@ export async function sendTransaction(params: ApiParams) {
const contractCallData = getCallDataArray(requestParamsObj.contractCallData);
const senderAddress = requestParamsObj.senderAddress;
const network = getNetworkFromChainId(state, requestParamsObj.chainId);
const {
privateKey: senderPrivateKey,
publicKey,
addressIndex,
} = await getKeysFromAddress(keyDeriver, network, state, senderAddress);

if (await isUpgradeRequired(network, senderAddress)) {
throw new Error('Upgrade required');
}

const { privateKey: senderPrivateKey, addressIndex } = await getKeysFromAddress(
keyDeriver,
network,
state,
senderAddress,
);
let maxFee = requestParamsObj.maxFee ? num.toBigInt(requestParamsObj.maxFee) : constants.ZERO;
if (maxFee === constants.ZERO) {
const { suggestedMaxFee } = await estimateFee(params);
Expand Down Expand Up @@ -77,7 +89,7 @@ export async function sendTransaction(params: ApiParams) {

logger.log(`sendTransaction:\ntxnInvocation: ${toJson(txnInvocation)}\nmaxFee: ${maxFee.toString()}}`);

const accountDeployed = await isAccountDeployed(network, publicKey);
const accountDeployed = await isAccountDeployed(network, senderAddress);
if (!accountDeployed) {
//Deploy account before sending the transaction
logger.log('sendTransaction:\nFirst transaction : send deploy transaction');
Expand Down Expand Up @@ -116,7 +128,8 @@ export async function sendTransaction(params: ApiParams) {
try {
return num.toHex(num.toBigInt(data));
} catch (e) {
throw new Error(`contractCallData could not be converted, ${e.message || e}`);
//data is already send to chain, hence we should not throw error
return '0x0';
}
}),
finalityStatus: TransactionStatus.RECEIVED,
Expand Down
25 changes: 13 additions & 12 deletions packages/starknet-snap/src/signMessage.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { toJson } from './utils/serializer';
import { signMessage as signMessageUtil, getKeysFromAddress } from './utils/starknetUtils';
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';
Expand All @@ -11,24 +11,25 @@ export async function signMessage(params: ApiParams) {
try {
const { state, wallet, keyDeriver, requestParams } = params;
const requestParamsObj = requestParams as SignMessageRequestParams;
const signerAddress = requestParamsObj.signerAddress;
const typedDataMessage = requestParamsObj.typedDataMessage;
const network = getNetworkFromChainId(state, requestParamsObj.chainId);

if (!requestParamsObj.signerAddress) {
throw new Error(
`The given signer address need to be non-empty string, got: ${toJson(requestParamsObj.signerAddress)}`,
);
logger.log(`signMessage:\nsignerAddress: ${signerAddress}\ntypedDataMessage: ${toJson(typedDataMessage)}`);

if (!signerAddress) {
throw new Error(`The given signer address need to be non-empty string, got: ${toJson(signerAddress)}`);
}

try {
validateAndParseAddress(requestParamsObj.signerAddress);
validateAndParseAddress(signerAddress);
} catch (err) {
throw new Error(`The given signer address is invalid: ${requestParamsObj.signerAddress}`);
throw new Error(`The given signer address is invalid: ${signerAddress}`);
}

const signerAddress = requestParamsObj.signerAddress;
const typedDataMessage = requestParamsObj.typedDataMessage;
const network = getNetworkFromChainId(state, requestParamsObj.chainId);

logger.log(`signMessage:\nsignerAddress: ${signerAddress}\ntypedDataMessage: ${toJson(typedDataMessage)}`);
if (await isUpgradeRequired(network, signerAddress)) {
throw new Error('Upgrade required');
}

const components = [];
addDialogTxt(components, 'Message', toJson(typedDataMessage));
Expand Down
1 change: 1 addition & 0 deletions packages/starknet-snap/src/types/snapState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface AccContract {
derivationPath: string;
deployTxnHash: string; // in hex
chainId: string; // in hex
upgradeRequired?: boolean;
}

export interface Erc20Token {
Expand Down
Loading
Loading