diff --git a/src/account/interface.ts b/src/account/interface.ts index eba6e4b4e..7327856d7 100644 --- a/src/account/interface.ts +++ b/src/account/interface.ts @@ -368,8 +368,6 @@ export abstract class AccountInterface extends ProviderInterface { * * @param typedData - TypedData object to be verified * @param signature - signature of the TypedData object - * @param signatureVerificationFunctionName - optional account contract verification function name override - * @param signatureVerificationResponse - optional response override { okResponse: string[]; nokResponse: string[]; error: string[] } * @returns true if the signature is valid, false otherwise * @throws {Error} if typedData is not a valid TypedData or the signature is not a valid signature */ @@ -381,8 +379,6 @@ export abstract class AccountInterface extends ProviderInterface { * * @param hash - hash to be verified * @param signature - signature of the hash - * @param signatureVerificationFunctionName - optional account contract verification function name override - * @param signatureVerificationResponse - optional response override { okResponse: string[]; nokResponse: string[]; error: string[] } * @returns true if the signature is valid, false otherwise * @throws {Error} if the signature is not a valid signature */ diff --git a/src/signer/interface.ts b/src/signer/interface.ts index beaea9bd3..68e94501e 100644 --- a/src/signer/interface.ts +++ b/src/signer/interface.ts @@ -11,33 +11,68 @@ export abstract class SignerInterface { /** * Method to get the public key of the signer * - * @returns format: hex-string + * @returns {string} hex-string + * @example + * ```typescript + * const mySigner = new Signer("0x123"); + * const result = await mySigner.getPubKey(); + * // result = "0x566d69d8c99f62bc71118399bab25c1f03719463eab8d6a444cd11ece131616" + * ``` */ public abstract getPubKey(): Promise; /** - * Signs a JSON object for off-chain usage with the Starknet private key and returns the signature + * Signs a JSON object for off-chain usage with the private key and returns the signature. * This adds a message prefix so it can't be interchanged with transactions * - * @param typedData - JSON object to be signed - * @param accountAddress + * @param {TypedData} typedData JSON object to be signed + * @param {string} accountAddress Hex string of the account's address + * @returns {Promise} the signature of the message + * @example + * ```typescript + * const mySigner = new Signer("0x123"); + * const myTypedData: TypedData = { + * domain: {name: "Example DApp", + * chainId: constants.StarknetChainId.SN_SEPOLIA, + * version: "0.0.3"}, + * types: {StarkNetDomain: [ + * { name: "name", type: "string" }, + * { name: "chainId", type: "felt" }, + * { name: "version", type: "string" }], + * Message: [{ name: "message", type: "felt" }]}, + * primaryType: "Message", message: {message: "1234"}}; + * const result = await mySigner.signMessage(myTypedData,"0x5d08a4e9188429da4e993c9bf25aafe5cd491ee2b501505d4d059f0c938f82d"); + * // result = Signature {r: 684915484701699003335398790608214855489903651271362390249153620883122231253n, + * // s: 1399150959912500412309102776989465580949387575375484933432871778355496929189n, recovery: 1} + * ``` + */ public abstract signMessage(typedData: TypedData, accountAddress: string): Promise; /** - * Signs transactions with the Starknet private key and returns the signature + * Signs transactions with the private key and returns the signature * - * @param transactions - Array of Call objects, each including:
- * - contractAddress
- * - entrypoint
- * - calldata
- * @param transactionsDetail - InvocationsSignerDetails object with:
- * - walletAddress
- * - chainId
- * - cairoVersion
- * - maxFee
- * - version
- * - nonce
+ * @param {Call[]} transactions array of Call objects + * @param {InvocationsSignerDetails} transactionsDetail InvocationsSignerDetails object + * @returns {Promise} the signature of the transaction + * @example + * ```typescript + * const mySigner = new Signer("0x123"); + * const calls: Call[] = [{ + * contractAddress: "0x1234567890123456789012345678901234567890", + * entrypoint: "functionName", + * calldata: [1, 2, 3] + * }]; + * const transactionsDetail: InvocationsSignerDetails = { + * walletAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', + * chainId: constants.StarknetChainId.SN_MAIN, + * cairoVersion: "1", + * maxFee: '0x1234567890abcdef', + * version: "0x0", nonce: 1}; + * const result = await mySigner.signTransaction(calls, transactionsDetail); + * // result = Signature {r: 304910226421970384958146916800275294114105560641204815169249090836676768876n, + * // s: 1072798866000813654190523783606274062837012608648308896325315895472901074693n, recovery: 0} + * ``` */ public abstract signTransaction( transactions: Call[], @@ -45,33 +80,53 @@ export abstract class SignerInterface { ): Promise; /** - * Signs a DEPLOY_ACCOUNT transaction with the Starknet private key and returns the signature + * Signs a DEPLOY_ACCOUNT transaction with the private key and returns the signature * - * @param transaction
- * - contractAddress
- * - chainId
- * - classHash
- * - constructorCalldata
- * - addressSalt
- * - maxFee
- * - version
- * - nonce
+ * @param {DeployAccountSignerDetails} transaction to deploy an account contract + * @returns {Promise} the signature of the transaction to deploy an account + * @example + * ```typescript + * const mySigner = new Signer("0x123"); + * const myDeployAcc: DeployAccountSignerDetails = { + * contractAddress: "0x65a822fbee1ae79e898688b5a4282dc79e0042cbed12f6169937fddb4c26641", + * version: "0x2", chainId: constants.StarknetChainId.SN_SEPOLIA, + * classHash: "0x5f3614e8671257aff9ac38e929c74d65b02d460ae966cd826c9f04a7fa8e0d4", + * constructorCalldata: [1, 2],addressSalt: 1234, + * nonce: 45, maxFee: 10 ** 15, tip: 0, paymasterData: [],accountDeploymentData: [], + * nonceDataAvailabilityMode: RPC.EDataAvailabilityMode.L1, + * feeDataAvailabilityMode: RPC.EDataAvailabilityMode.L1, + * resourceBounds: stark.estimateFeeToBounds(constants.ZERO), + * } + * const result = await mySigner.signDeployAccountTransaction(myDeployAcc); + * // result = Signature {r: 2871311234341436528393212130310036951068553852419934781736214693308640202748n, + * // s: 1746271646048888422437132495446973163454853863041370993384284773665861377605n, recovery: 1} + * ``` */ public abstract signDeployAccountTransaction( transaction: DeployAccountSignerDetails ): Promise; /** - * Signs a DECLARE transaction with the Starknet private key and returns the signature + * Signs a DECLARE transaction with the private key and returns the signature * - * @param transaction
- * - classHash
- * - compiledClassHash? - used for Cairo1
- * - senderAddress
- * - chainId
- * - maxFee
- * - version
- * - nonce
+ * @param {DeclareSignerDetails} transaction to declare a class + * @returns {Promise} the signature of the transaction to declare a class + * @example + * ```typescript + * const mySigner = new Signer("0x123"); + * const myDeclare: DeclareSignerDetails = { + * version: "0x2", chainId: constants.StarknetChainId.SN_SEPOLIA, + * senderAddress: "0x65a822fbee1ae79e898688b5a4282dc79e0042cbed12f6169937fddb4c26641", + * classHash: "0x5f3614e8671257aff9ac38e929c74d65b02d460ae966cd826c9f04a7fa8e0d4", + * nonce: 45, maxFee: 10 ** 15, tip: 0, paymasterData: [], accountDeploymentData: [], + * nonceDataAvailabilityMode: RPC.EDataAvailabilityMode.L1, + * feeDataAvailabilityMode: RPC.EDataAvailabilityMode.L1, + * resourceBounds: stark.estimateFeeToBounds(constants.ZERO), +} + * const result = await mySigner.signDeclareTransaction(myDeclare); + * // result = Signature {r: 2432056944313955951711774394836075930010416436707488863728289188289211995670n, + * // s: 3407649393310177489888603098175002856596469926897298636282244411990343146307n, recovery: 1} + * ``` */ public abstract signDeclareTransaction(transaction: DeclareSignerDetails): Promise; } diff --git a/src/utils/hash/classHash.ts b/src/utils/hash/classHash.ts index ac9166eea..23801d0e9 100644 --- a/src/utils/hash/classHash.ts +++ b/src/utils/hash/classHash.ts @@ -33,8 +33,16 @@ export function computePoseidonHash(a: BigNumberish, b: BigNumberish): string { } /** - * Compute pedersen hash from data - * @returns format: hex-string - pedersen hash + * Compute Pedersen hash from data + * + * @param {BigNumberish[]} data Array of data to compute Pedersen hash on + * @returns {string} hex-string of Pedersen hash + * + * @example + * ```typescript + * const result = hash.computeHashOnElements(['0xabc', '0x123', '0xabc123']) + * // result = 0x148141e8f7db29d005a0187669a56f0790d7e8c2c5b2d780e4d8b9e436a5521 + * ``` */ export function computeHashOnElements(data: BigNumberish[]): string { return [...data, data.length] @@ -50,14 +58,24 @@ export function computePoseidonHashOnElements(data: BigNumberish[]) { /** * Calculate contract address from class hash - * @returns format: hex-string + * + * @param {BigNumberish} salt Salt to be used for hashing + * @param {BigNumberish} classHash Class hash of contract to generate address for + * @param {RawArgs} constructorCalldata Call data for contract constructor + * @param {BigNumberish} deployerAddress Address of contract deployer + * @returns {string} hex-string + * @example + * ```typescript + * const result = hash.calculateContractAddressFromHash(1234, 0x1cf4fe5d37868d25524cdacb89518d88bf217a9240a1e6fde71cc22c429e0e3, [1234, true, false], 0x052fb1a9ab0db3c4f81d70fea6a2f6e55f57c709a46089b25eeec0e959db3695); + * // result = 0x5fb03d3a88d8e474976932f927ff6a9e332e06ed36642ea3e8c7e38bf010f76 + * ``` */ export function calculateContractAddressFromHash( salt: BigNumberish, classHash: BigNumberish, constructorCalldata: RawArgs, deployerAddress: BigNumberish -) { +): string { const compiledCalldata = CallData.compile(constructorCalldata); const constructorCalldataHash = computeHashOnElements(compiledCalldata); @@ -86,11 +104,16 @@ function nullSkipReplacer(key: string, value: any) { } /** - * Format json-string to conform starknet json-string - * @param json json-string - * @returns format: json-string + * Format json-string without spaces to conform starknet json-string + * @param {string} json json-string without spaces + * @returns {string} json-string with additional spaces after `:` and `,` + * @example + * ```typescript + * const result = hash.formatSpaces("{'onchain':true,'isStarknet':true}"); + * // result = "{'onchain': true, 'isStarknet': true}" + * ``` */ -export function formatSpaces(json: string) { +export function formatSpaces(json: string): string { let insideQuotes = false; const newString = []; // eslint-disable-next-line no-restricted-syntax @@ -110,7 +133,9 @@ export function formatSpaces(json: string) { /** * Compute hinted class hash for legacy compiled contract (Cairo 0) - * @returns format: hex-string + * @param {LegacyCompiledContract} compiledContract + * @returns {string} hex-string + * No example, as this function is not exported to user */ export default function computeHintedClassHash(compiledContract: LegacyCompiledContract) { const { abi, program } = compiledContract; @@ -122,7 +147,14 @@ export default function computeHintedClassHash(compiledContract: LegacyCompiledC /** * Computes the class hash for legacy compiled contract (Cairo 0) - * @returns format: hex-string + * @param {LegacyCompiledContract | string} contract legacy compiled contract content + * @returns {string} hex-string of class hash + * @example + * ```typescript + * const compiledCairo0 = json.parse(fs.readFileSync("./cairo0contract.json").toString("ascii")); + * const result=hash.computeLegacyContractClassHash(compiledCairo0); + * // result = "0x4a5cae61fa8312b0a3d0c44658b403d3e4197be80027fd5020ffcdf0c803331" + * ``` */ export function computeLegacyContractClassHash(contract: LegacyCompiledContract | string) { const compiledContract = isString(contract) @@ -183,17 +215,21 @@ function hashEntryPoint(data: ContractEntryPointFields[]) { * Compute hash of the bytecode for Sierra v1.5.0 onwards (Cairo 2.6.0) * Each segment is Poseidon hashed. * The global hash is : 1 + PoseidonHash(len0, h0, len1, h1, ...) - * @param casm compiled Sierra CASM file content. - * @returns the bytecode hash as bigint. + * @param {CompiledSierraCasm} casm compiled Sierra CASM file content. + * @returns {bigint} the bytecode hash as bigint. + * @example + * ```typescript + * const compiledCasm = json.parse(fs.readFileSync("./contractC260.casm.json").toString("ascii")); + * const result = hash.hashByteCodeSegments(compiledCasm); + * // result = 80499149343908132326491548897246987792410240503053732367044713070598981699n + * ``` */ export function hashByteCodeSegments(casm: CompiledSierraCasm): bigint { const byteCode: bigint[] = casm.bytecode.map((n) => BigInt(n)); const bytecodeSegmentLengths: number[] = casm.bytecode_segment_lengths ?? []; - let segmentStart = 0; const hashLeaves = bytecodeSegmentLengths.flatMap((len) => { const segment = byteCode.slice(segmentStart, (segmentStart += len)); - return [BigInt(len), poseidonHashMany(segment)]; }); return 1n + poseidonHashMany(hashLeaves); @@ -201,9 +237,16 @@ export function hashByteCodeSegments(casm: CompiledSierraCasm): bigint { /** * Compute compiled class hash for contract (Cairo 1) - * @returns format: hex-string + * @param {CompiledSierraCasm} casm Cairo 1 compiled contract content + * @returns {string} hex-string of class hash + * @example + * ```typescript + * const compiledCasm = json.parse(fs.readFileSync("./cairo260.casm.json").toString("ascii")); + * const result = hash.computeCompiledClassHash(compiledCasm); + * // result = "0x4087905743b4fa2b3affc1fc71333f1390c8c5d1e8ea47d6ba70786de3fc01a" +``` */ -export function computeCompiledClassHash(casm: CompiledSierraCasm) { +export function computeCompiledClassHash(casm: CompiledSierraCasm): string { const COMPILED_CLASS_VERSION = 'COMPILED_CLASS_V1'; // Hash compiled class version @@ -248,9 +291,16 @@ function hashAbi(sierra: CompiledSierra) { /** * Compute sierra contract class hash (Cairo 1) - * @returns format: hex-string + * @param {CompiledSierra} sierra Cairo 1 Sierra contract content + * @returns {string} hex-string of class hash + * @example + * ```typescript + * const compiledSierra = json.parse(fs.readFileSync("./cairo260.sierra.json").toString("ascii")); + * const result = hash.computeSierraContractClassHash(compiledSierra); + * // result = "0x67b6b4f02baded46f02feeed58c4f78e26c55364e59874d8abfd3532d85f1ba" +``` */ -export function computeSierraContractClassHash(sierra: CompiledSierra) { +export function computeSierraContractClassHash(sierra: CompiledSierra): string { const CONTRACT_CLASS_VERSION = 'CONTRACT_CLASS_V0.1.0'; // Hash class version @@ -285,9 +335,16 @@ export function computeSierraContractClassHash(sierra: CompiledSierra) { /** * Compute ClassHash (sierra or legacy) based on provided contract - * @returns format: hex-string + * @param {CompiledContract | string} contract Cairo 1 contract content + * @returns {string} hex-string of class hash + * @example + * ```typescript + * const compiledSierra = json.parse(fs.readFileSync("./cairo260.sierra.json").toString("ascii")); + * const result = hash.computeContractClassHash(compiledSierra); + * // result = "0x67b6b4f02baded46f02feeed58c4f78e26c55364e59874d8abfd3532d85f1ba" +``` */ -export function computeContractClassHash(contract: CompiledContract | string) { +export function computeContractClassHash(contract: CompiledContract | string): string { const compiledContract = isString(contract) ? parse(contract) : contract; if ('sierra_program' in compiledContract) { diff --git a/src/utils/provider.ts b/src/utils/provider.ts index 0f34f459a..757189824 100644 --- a/src/utils/provider.ts +++ b/src/utils/provider.ts @@ -26,17 +26,43 @@ import type { GetTransactionReceiptResponse } from './transactionReceipt'; /** * Helper - Async Sleep for 'delay' time + * + * @param {number} delay - Number of milliseconds to delay + * @returns {Promise} + * @example + * ```typescript + * await provider.wait(1000) // 1000 milliseconds == 1 second + * ``` */ -export function wait(delay: number) { +export function wait(delay: number): Promise { return new Promise((res) => { setTimeout(res, delay); }); } /** - * Create Sierra Contract Class from a given Compiled Sierra + * Create Sierra compressed Contract Class from a given Compiled Sierra * * CompiledSierra -> SierraContractClass + * + * @param {CompiledSierra} contract sierra code from the Cairo compiler + * @returns {SierraContractClass} compressed Sierra + * @example + * ```typescript + * const result = provider.createSierraContractClass({ + "sierra_program": [ + "0x1", + "0x4", + "0x0", + "0x2", + "0x4", + "0x1", + "0x3b4", + "0x4c", + "0x65", + "0x52616e6765436865636b",...}) + * // result = {sierra_program: 'H4sIAAAAAAAAA6x9WZbsrI7uVGqd53qgb8ZynwzYY7jDv5JAAmxHZuQ+96yq/L0jIzEINZ8axP/5j/q/+j//+z/wH9f/o/p/zPbh+Iot49+u9v8G3//rTdDhDDF4Z0MKPthQ+m+S2v6n1S//638VvdXW2PQ6RvxuDG+jiybCXKJ7Hef6ZRi9E+Q89WmKLilfqbrsL6PUCf8...} + * ``` */ export function createSierraContractClass(contract: CompiledSierra): SierraContractClass { const result = { ...contract } as any; @@ -48,9 +74,25 @@ export function createSierraContractClass(contract: CompiledSierra): SierraContr } /** - * Create Contract Class from a given CompiledContract or string - * - * (CompiledContract or string) -> ContractClass + * Create a compressed contract from a given compiled Cairo 0 & 1 contract or a string. + * @param {CompiledContract | string} contract - Compiled Cairo 0 or Cairo 1 contract, or string + * @returns {ContractClass} Cairo 0 or Cairo 1 compressed contract + * @example + * ```typescript + * const result = provider.parseContract({ + "sierra_program": [ + "0x1", + "0x4", + "0x0", + "0x2", + "0x4", + "0x1", + "0x3b4", + "0x4c", + "0x65", + "0x52616e6765436865636b",...}) + * // result = {sierra_program: 'H4sIAAAAAAAAA6x9WZbsrI7uVGqd53qgb8ZynwzYY7jDv5JAAmxHZuQ+96yq/L0jIzEINZ8axP/5j/q/+j//+z/wH9f/o/p/zPbh+Iot49+u9v8G3//rTdDhDDF4Z0MKPthQ+m+S2v6n1S//638VvdXW2PQ6RvxuDG+jiybCXKJ7Hef6ZRi9E+Q89WmKLilfqbrsL6PUCf8...} + * ``` */ export function parseContract(contract: CompiledContract | string): ContractClass { const parsedContract = isString(contract) ? (parse(contract) as CompiledContract) : contract; @@ -67,9 +109,15 @@ export function parseContract(contract: CompiledContract | string): ContractClas /** * Return randomly select available public node - * @param networkName NetworkName - * @param mute mute public node warning - * @returns default node url + * @param {NetworkName} networkName NetworkName + * @param {boolean} mute mute public node warning + * @returns {string} default node url + * @example + * ```typescript + * const result= provider.getDefaultNodeUrl(constants.NetworkName.SN_MAIN,false); + * // console : "Using default public node url, please provide nodeUrl in provider options!" + * // result = "https://starknet-mainnet.public.blastapi.io/rpc/v0_7" + * ``` */ export const getDefaultNodeUrl = (networkName?: NetworkName, mute: boolean = false): string => { if (!mute) { @@ -82,7 +130,15 @@ export const getDefaultNodeUrl = (networkName?: NetworkName, mute: boolean = fal }; /** - * [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L148-L153) + * Return the hash formatted as a string + * @see https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L148-L153 + * @param {BigNumberish} hashValue NetworkName + * @returns {string} hash as a string + * @example + * ```typescript + * const result= provider.formatHash(123n); + * // result = "0x7b" + * ``` */ export function formatHash(hashValue: BigNumberish): string { if (isString(hashValue)) return hashValue; @@ -90,7 +146,16 @@ export function formatHash(hashValue: BigNumberish): string { } /** - * [Reference](https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L156-L161) + * Return the ID of a transaction + * @see https://github.com/starkware-libs/cairo-lang/blob/fc97bdd8322a7df043c87c371634b26c15ed6cee/src/starkware/starknet/services/api/feeder_gateway/feeder_gateway_client.py#L156-L161 + * @param {BigNumberish} [txHash] Transaction hash + * @param {BigNumberish} [txId] Transaction ID (one of the 2 params is required) + * @returns {string} transaction identifier + * @example + * ```typescript + * const result = provider.txIdentifier(undefined, 123n); + * // result = "transactionId=0x7b" + * ``` */ export function txIdentifier(txHash?: BigNumberish, txId?: BigNumberish): string { if (!txHash) { @@ -104,6 +169,8 @@ export function txIdentifier(txHash?: BigNumberish, txId?: BigNumberish): string export const validBlockTags = Object.values(BlockTag); /** + * This class is formatting the identifier of a block. + * * hex string and BigInt are detected as block hashes. identifier return { block_hash: hash } * * decimal string and number are detected as block numbers. identifier return { block_number: number } @@ -111,12 +178,26 @@ export const validBlockTags = Object.values(BlockTag); * text string are detected as block tag. identifier return tag * * null is detected as 'pending' block tag. identifier return 'pending' + * @example + * ```typescript + * const result = new provider.Block(null).identifier; + * // result = "pending" + * ``` */ export class Block { + /** + * @param {BlockIdentifier} hash if not null, contains the block hash + */ hash: BlockIdentifier = null; + /** + * @param {BlockIdentifier} number if not null, contains the block number + */ number: BlockIdentifier = null; + /** + * @param {BlockIdentifier} tag if not null, contains "pending" or "latest" + */ tag: BlockIdentifier = null; private setIdentifier(__identifier: BlockIdentifier): void { @@ -143,11 +224,26 @@ export class Block { } } + /** + * Create a Block instance + * @param {BlockIdentifier} _identifier hex string and BigInt are detected as block hashes. + * decimal string and number are detected as block numbers. + * text string are detected as block tag. + * null is considered as a 'pending' block tag. + */ constructor(_identifier: BlockIdentifier) { this.setIdentifier(_identifier); } // TODO: fix any + /** + * @returns {any} the identifier as a string + * @example + * ```typescript + * const result = new provider.Block(123456n).queryIdentifier; + * // result = "blockHash=0x1e240" + * ``` + */ get queryIdentifier(): any { if (this.number !== null) { return `blockNumber=${this.number}`; @@ -161,6 +257,14 @@ export class Block { } // TODO: fix any + /** + * @returns {any} the identifier as an object + * @example + * ```typescript + * const result = new provider.Block(56789).identifier; + * // result = { block_number: 56789 } + * ``` + */ get identifier(): any { if (this.number !== null) { return { block_number: this.number }; @@ -173,6 +277,16 @@ export class Block { return this.tag; } + /** + * change the identifier of an existing Block instance + * @example + * ```typescript + * const myBlock = new provider.Block("latest"); + * myBlock.identifier ="0x3456789abc"; + * const result = myBlock.identifier; + * // result = { block_hash: '0x3456789abc' } + * ``` + */ set identifier(_identifier: BlockIdentifier) { this.setIdentifier(_identifier); } @@ -185,8 +299,23 @@ export class Block { /** * Check if the given transaction details is a V3 transaction. * - * @param {InvocationsDetailsWithNonce} details - The transaction details to be checked. - * @return {boolean} - Returns true if the transaction is a V3 transaction, otherwise false. + * @param {InvocationsDetailsWithNonce} details The transaction details to be checked. + * @return {boolean} Returns true if the transaction is a V3 transaction, otherwise false. + * @example + * ```typescript + * const invocation: InvocationsDetailsWithNonce = { + * nonce: 1, + * version: 3, + * maxFee: 10 ** 15, + * feeDataAvailabilityMode: RPC.EDataAvailabilityMode.L1, + * tip: 10 ** 13, + * paymasterData: [], + * resourceBounds: { + * l1_gas: { max_amount: num.toHex(10 ** 14), max_price_per_unit: num.toHex(50) }, + * l2_gas: { max_amount: num.toHex(0), max_price_per_unit: num.toHex(0) }}}; + * const result = provider.isV3Tx(invocation); + * // result = true + * ``` */ export function isV3Tx(details: InvocationsDetailsWithNonce): details is V3TransactionDetails { const version = details.version ? toHex(details.version) : ETransactionVersion.V3; @@ -196,11 +325,16 @@ export function isV3Tx(details: InvocationsDetailsWithNonce): details is V3Trans /** * Determines if the given response matches the specified version. * - * @param {('0.5' | '0.6' | '0.7')} version - The version to compare against the response. - * @param {string} response - The response to check against the version. - * @returns {boolean} - True if the response matches the version, false otherwise. + * @param {('0.5' | '0.6' | '0.7')} version The version to compare against the response. + * @param {string} response The response to check against the version. + * @returns {boolean} True if the response matches the version, false otherwise. + * @example + * ``` typescript + * const result = provider.isVersion("0.7","0_7"); + * // result = false + * ``` */ -export function isVersion(version: '0.5' | '0.6' | '0.7', response: string) { +export function isVersion(version: '0.5' | '0.6' | '0.7', response: string): boolean { const [majorS, minorS] = version.split('.'); const [majorR, minorR] = response.split('.'); @@ -209,6 +343,14 @@ export function isVersion(version: '0.5' | '0.6' | '0.7', response: string) { /** * Guard Pending Block + * @param {GetBlockResponse} response answer of myProvider.getBlock() + * @return {boolean} true if block is the pending block + * @example + * ```typescript + * const block = await myProvider.getBlock("pending"); + * const result = provider.isPendingBlock(block); + * // result = true + * ``` */ export function isPendingBlock(response: GetBlockResponse): response is PendingBlock { return response.status === 'PENDING'; @@ -216,6 +358,15 @@ export function isPendingBlock(response: GetBlockResponse): response is PendingB /** * Guard Pending Transaction + * @param {GetTransactionReceiptResponse} response transaction Receipt + * @return {boolean} true if the transaction is part of the pending block + * @example + * ```typescript + * const block = await myProvider.getBlockWithTxs("pending"); + * const txR = await myProvider.getTransactionReceipt(block.transactions[0].transaction_hash); + * const result = provider.isPendingTransaction(txR); + * // result = true + * ``` */ export function isPendingTransaction(response: GetTransactionReceiptResponse): boolean { return !('block_hash' in response); @@ -223,7 +374,14 @@ export function isPendingTransaction(response: GetTransactionReceiptResponse): b /** * Guard Pending State Update - * ex. if(isPendingStateUpdate(stateUpdate)) throw Error('Update must be final') + * @param {StateUpdateResponse} response State of a block + * @return {boolean} true if the block is pending + * @example + * ```typescript + * const state: StateUpdateResponse = await myProvider.getStateUpdate("pending"); + * const result = provider.isPendingStateUpdate(state); + * // result = true + * ``` */ export function isPendingStateUpdate( response: StateUpdateResponse diff --git a/src/utils/shortString.ts b/src/utils/shortString.ts index bd4d8953a..5710711f1 100644 --- a/src/utils/shortString.ts +++ b/src/utils/shortString.ts @@ -4,21 +4,46 @@ import { isHex, isStringWholeNumber } from './num'; /** * Test if string contains only ASCII characters (string can be ascii text) + * @param {string} str The string to test + * @returns {boolean} Returns true if the string contains only ASCII characters, otherwise false + * @example + * ```typescript + * const result = shortString.isASCII("Hello, world!"); + * // result = true + * const result = shortString.isASCII("Hello, 世界!"); + * // result = false + * ``` */ -export function isASCII(str: string) { +export function isASCII(str: string): boolean { // eslint-disable-next-line no-control-regex return /^[\x00-\x7F]*$/.test(str); } /** - * Test if string is a Cairo short string (string has less or equal 31 characters) + * Test if a string is a Cairo short string (string with less or equal 31 characters) + * @param {string} str the string to test + * @returns {boolean} Returns true if the string has less than or equal to 31 characters, otherwise false. + * @example + * ```typescript + * const result = shortString.isShortString("Hello, world!"); + * // result = true + * ``` */ -export function isShortString(str: string) { +export function isShortString(str: string): boolean { return str.length <= TEXT_TO_FELT_MAX_LEN; } /** - * Test if string contains only numbers (string can be converted to decimal number) + * Test if string contains only numbers (string can be converted to decimal integer number) + * @param {string} str the string to test. + * @returns {boolean} Returns true if the string contains only numbers, otherwise false. + * @example + * ```typescript + * const result = shortString.isDecimalString("12345"); + * // result = true + * const result = shortString.isDecimalString("12a45"); + * // result = false + * ``` */ export function isDecimalString(str: string): boolean { return /^[0-9]*$/i.test(str); @@ -26,16 +51,29 @@ export function isDecimalString(str: string): boolean { /** * Checks if a given value is a string. - * - * @param {unknown} value - The value to be checked. - * @return {boolean} - Returns true if the value is a string, false otherwise. + * @param {unknown} value the value to be checked. + * @return {boolean} returns true if the value is a string, false otherwise. + * @example + * ```typescript + * const result = shortString.isString("12345"); + * // result = true + * ``` */ export function isString(value: unknown): value is string { return typeof value === 'string'; } /** - * Test if value is a free-from string text, and not a hex string or number string + * Test if value is a pure string text, and not a hex string or number string + * @param {any} val the value to test + * @returns {boolean} returns true if the value is a free-form string text, otherwise false + * @example + * ```typescript + * const result = shortString.isText("Hello, world!"); + * // result = true + * const result = shortString.isText("0x7aec92f706"); + * // result = false + * ``` */ export function isText(val: any) { return isString(val) && !isHex(val) && !isStringWholeNumber(val); @@ -43,16 +81,37 @@ export function isText(val: any) { /** * Test if value is short text + * @param {any} val - The item to test + * @returns {boolean} Returns true if the value is a short text (string has less or equal 31 characters), otherwise false + * @example + * ```typescript + * const result = shortString.isShortText("Hello, world!"); + * // result = true + * ``` */ export const isShortText = (val: any) => isText(val) && isShortString(val); /** * Test if value is long text + * @param {any} val the value to test + * @returns {boolean} returns true if the value is a long text(string has more than 31 characters), otherwise false. + * @example + * ```typescript + * const result = shortString.isLongText("Hello, world! this is some random long string to enable you test isLongText function."); + * // result = true + * ``` */ export const isLongText = (val: any) => isText(val) && !isShortString(val); /** - * Split long text into short strings + * Split long text (string greater than 31 characters) into short strings (string lesser or equal 31 characters) + * @param {string} longStr the long text (string greater than 31 characters) to split + * @returns {string[]} an array of short strings (string lesser or equal 31 characters). + * @example + * ```typescript + * const result = shortString.splitLongString("Hello, world! we just testing splitLongString function."); + * // result = [ 'Hello, world! we just testing s', 'plitLongString function.' ] + * ``` */ export function splitLongString(longStr: string): string[] { const regex = RegExp(`[^]{1,${TEXT_TO_FELT_MAX_LEN}}`, 'g'); @@ -60,13 +119,13 @@ export function splitLongString(longStr: string): string[] { } /** - * Convert an ASCII string to a hexadecimal string. - * @param str short string (ASCII string, 31 characters max) - * @returns format: hex-string; 248 bits max + * Convert an ASCII short string to a hexadecimal string. + * @param {string} str short string (ASCII string, 31 characters max) + * @returns {string} hex-string with 248 bits max * @example * ```typescript - * const myEncodedString: string = encodeShortString("uri/pict/t38.jpg"); - * // return hex string (ex."0x7572692f706963742f7433382e6a7067") + * const result = shortString.encodeShortString("uri/pict/t38.jpg"); + * // result = "0x7572692f706963742f7433382e6a7067" * ``` */ export function encodeShortString(str: string): string { @@ -77,12 +136,12 @@ export function encodeShortString(str: string): string { /** * Convert a hexadecimal or decimal string to an ASCII string. - * @param str representing a 248 bit max number (ex. "0x1A4F64EA56" or "236942575435676423") - * @returns format: short string; 31 characters max + * @param {string} str representing a 248 bit max number (ex. "0x1A4F64EA56" or "236942575435676423") + * @returns {string} short string; 31 characters max * @example * ```typescript - * const myDecodedString: string = decodeShortString("0x7572692f706963742f7433382e6a7067"); - * // return string (ex."uri/pict/t38.jpg") + * const result = shortString.decodeShortString("0x7572692f706963742f7433382e6a7067"); + * // result = "uri/pict/t38.jpg" * ``` */ export function decodeShortString(str: string): string { diff --git a/src/utils/stark.ts b/src/utils/stark.ts index dc9a995a2..fc9671366 100644 --- a/src/utils/stark.ts +++ b/src/utils/stark.ts @@ -26,10 +26,17 @@ import { import { isString } from './shortString'; /** - * Compress compiled Cairo program + * Compress compiled Cairo 0 program * * [Reference](https://github.com/starkware-libs/cairo-lang/blob/master/src/starkware/starknet/services/api/gateway/transaction.py#L54-L58) - * @param jsonProgram Representing the compiled cairo program + * @param {Program | string} jsonProgram Representing the compiled Cairo 0 program + * @return {CompressedProgram} Compressed Cairo 0 program + * @example + * ```typescript + * const contractCairo0 = json.parse(fs.readFileSync("./cairo0contract.json").toString("ascii")); + * const result = stark.compressProgram(contractCairo0); + * // result = "H4sIAAAAAAAAA+1dC4/bOJL+K4aBu01me7r5EEUyixzQk/TuB..." + * ``` */ export function compressProgram(jsonProgram: Program | string): CompressedProgram { const stringified = isString(jsonProgram) ? jsonProgram : stringify(jsonProgram); @@ -38,9 +45,32 @@ export function compressProgram(jsonProgram: Program | string): CompressedProgra } /** - * Decompress compressed compiled Cairo program - * @param base64 Compressed program - * @returns Parsed decompressed compiled Cairo program + * Decompress compressed compiled Cairo 0 program + * @param {CompressedProgram} base64 Compressed Cairo 0 program + * @returns {Object | CompressedProgram} Parsed decompressed compiled Cairo 0 program + * @example + * ```typescript + * const contractCairo0 = json.parse(fs.readFileSync("./cairo0contract.json").toString("ascii")); + * const compressedCairo0 = stark.compressProgram(contractCairo0); + * const result = stark.decompressProgram(compressedCairo0); + * // result = { + * // abi: [ + * // { + * // inputs: [Array], + * // name: 'increase_balance', + * // outputs: [], + * // type: 'function' + * // } + * // ], + * // entry_points_by_type: { CONSTRUCTOR: [], EXTERNAL: [ [Object], [Object] ], L1_HANDLER: [] }, + * // program: { + * // attributes: [], + * // builtins: [ 'pedersen', 'range_check' ], + * // compiler_version: '0.10.2', + * // data: [ + * // '0x480680017fff8000', + * // ... + * ``` */ export function decompressProgram(base64: CompressedProgram) { if (Array.isArray(base64)) return base64; @@ -50,6 +80,12 @@ export function decompressProgram(base64: CompressedProgram) { /** * Random Address based on random keyPair + * @returns {string} an hex string of a random Starknet address + * @example + * ```typescript + * const result = stark.randomAddress(); + * // result = "0x51fc8126a13cd5ddb29a71ca399cb1e814f086f5af1b502d7151c14929554f" + * ``` */ export function randomAddress(): string { const randomKeyPair = utils.randomPrivateKey(); @@ -67,7 +103,16 @@ export function makeAddress(input: string): string { /** * Format Signature to standard type (hex array) - * @returns Custom hex array or weierstrass.SignatureType hex array + * @param {Signature} [sig] + * @returns {ArraySignatureType} Custom hex string array + * @throws {Error} if sig not defined, or wrong format + * @example + * ```typescript + * const signature = ec.starkCurve.sign("0x12de34", "0x3487123eac"); + * const result = stark.formatSignature(signature); + * // result = ['0xba8eecee2d69c417e8c6a20cf331c821f716b58ba9e47166c7476afdb38997', + * // '0x69ef7438c94104839a6e2aa2385482a77399d2f46e894ae4f50ab6d69239d1c'] + * ``` */ export function formatSignature(sig?: Signature): ArraySignatureType { if (!sig) throw Error('formatSignature: provided signature is undefined'); @@ -84,6 +129,16 @@ export function formatSignature(sig?: Signature): ArraySignatureType { /** * Format Signature to decimal string array + * @param {Signature} [sig] + * @returns {ArraySignatureType} Custom hex string array + * @throws {Error} if sig not defined, or wrong format + * @example + * ```typescript + * const signature = ec.starkCurve.sign("0x12de34", "0x3487123eac"); + * const result = stark.signatureToDecimalArray(signature); + * // result = ['329619989660444495690615805546674399714973829707166906185976654753023887767', + * // '2994745480203297689255012826403147585778741462125743754529207781488706428188'] + * ``` */ export function signatureToDecimalArray(sig?: Signature): ArraySignatureType { return bigNumberishArrayToDecimalStringArray(formatSignature(sig)); @@ -91,13 +146,31 @@ export function signatureToDecimalArray(sig?: Signature): ArraySignatureType { /** * Format Signature to hex string array + * @param {Signature} [sig] + * @returns {ArraySignatureType} Custom hex string array + * @throws {Error} if sig not defined, or wrong format + * @example + * ```typescript + * const signature = ec.starkCurve.sign("0x12de34", "0x3487123eac"); + * const result = stark.signatureToHexArray(signature); + * // result = ['0xba8eecee2d69c417e8c6a20cf331c821f716b58ba9e47166c7476afdb38997', + * // '0x69ef7438c94104839a6e2aa2385482a77399d2f46e894ae4f50ab6d69239d1c'] + * ``` */ export function signatureToHexArray(sig?: Signature): ArraySignatureType { return bigNumberishArrayToHexadecimalStringArray(formatSignature(sig)); } /** - * Convert estimated fee to max fee with overhead + * Convert estimated fee to max fee including a margin + * @param {BigNumberish} estimatedFee - The estimated fee + * @param {number} [overhead = feeMarginPercentage.MAX_FEE] - The overhead added to the gas + * @returns {bigint} The maximum fee with the margin + * @example + * ```typescript + * const result = stark.estimatedFeeToMaxFee("8982300000000", 50); + * // result = "13473450000000n" + * ``` */ export function estimatedFeeToMaxFee( estimatedFee: BigNumberish, @@ -109,17 +182,25 @@ export function estimatedFeeToMaxFee( /** * Calculates the maximum resource bounds for fee estimation. * - * @param {FeeEstimate|0n} estimate - The estimate for the fee. If a BigInt is provided, - * the returned bounds will be set to '0x0'. - * @param {number} [amountOverhead=feeMarginPercentage.L1_BOUND_MAX_AMOUNT] - The percentage - * overhead added to - * the gas consumed or - * overall fee amount. - * @param {number} [priceOverhead=feeMarginPercentage.L1_BOUND_MAX_PRICE_PER_UNIT] - The percentage - * overhead added to - * the gas price per unit. - * @throws {Error} If the estimate object is undefined or does not have the required properties. + * @param {FeeEstimate | 0n} estimate The estimate for the fee. If a BigInt is provided, the returned bounds will be set to '0x0'. + * @param {number} [amountOverhead = feeMarginPercentage.L1_BOUND_MAX_AMOUNT] - The percentage overhead added to the gas consumed or overall fee amount. + * @param {number} [priceOverhead = feeMarginPercentage.L1_BOUND_MAX_PRICE_PER_UNIT] The percentage overhead added to the gas price per unit. * @returns {ResourceBounds} The maximum resource bounds for fee estimation. + * @throws {Error} If the estimate object is undefined or does not have the required properties. + * @example + * ```typescript + * const feeEstimated: FeeEstimate = { + gas_consumed: "0x3456a", + gas_price: "0xa45567567567ae4", + overall_fee: "0x2198F463A77A899A5668", + unit: "WEI" +}; +const result = stark.estimateFeeToBounds(feeEstimated, 70, 50); + * // result = { + * // l2_gas: { max_amount: '0x0', max_price_per_unit: '0x0' }, + * // l1_gas: { max_amount: '0x58f9a', max_price_per_unit: '0xf6801b01b01b856' } + * // } + * ``` */ export function estimateFeeToBounds( estimate: FeeEstimate | 0n, @@ -151,11 +232,16 @@ export function estimateFeeToBounds( /** * Converts the data availability mode from EDataAvailabilityMode to EDAMode. * - * @param {EDataAvailabilityMode} dam - The data availability mode to be converted. + * @param {EDataAvailabilityMode} dam The data availability mode to be converted. * @return {EDAMode} The converted data availability mode. * @throws {Error} If the data availability mode is not a valid value. + * @example + * ```typescript + * const result = stark.intDAM(RPC.EDataAvailabilityMode.L1); + * // result = 0 + * ``` */ -export function intDAM(dam: EDataAvailabilityMode) { +export function intDAM(dam: EDataAvailabilityMode): EDAMode { if (dam === EDataAvailabilityMode.L1) return EDAMode.L1; if (dam === EDataAvailabilityMode.L2) return EDAMode.L2; throw Error('EDAM conversion'); @@ -164,11 +250,20 @@ export function intDAM(dam: EDataAvailabilityMode) { /** * Convert to ETransactionVersion or throw an error. * Return providedVersion is specified else return defaultVersion - * @param defaultVersion BigNumberish - * @param providedVersion BigNumberish | undefined - * @returns ETransactionVersion + * @param {BigNumberish} defaultVersion default estimate transaction version + * @param {BigNumberish} [providedVersion] estimate transaction version + * @returns {ETransactionVersion} if providedVersion is not provided, returns the default estimate version, else return the provided version + * @throws {Error} if estimate transaction version or default estimate transaction version is unknown + * @example + * ```typescript + * const result = stark.toTransactionVersion("0x100000000000000000000000000000003", stark.toFeeVersion(2)); + * // result = "0x100000000000000000000000000000002" + * ``` */ -export function toTransactionVersion(defaultVersion: BigNumberish, providedVersion?: BigNumberish) { +export function toTransactionVersion( + defaultVersion: BigNumberish, + providedVersion?: BigNumberish +): ETransactionVersion { const providedVersion0xs = providedVersion ? toHex(providedVersion) : undefined; const defaultVersion0xs = toHex(defaultVersion); @@ -184,7 +279,14 @@ export function toTransactionVersion(defaultVersion: BigNumberish, providedVersi /** * Convert Transaction version to Fee version or throw an error - * @param providedVersion BigNumberish | undefined + * @param {BigNumberish} [providedVersion] 0..3 number representing the transaction version + * @returns {ETransactionVersion} the fee estimation version corresponding to the transaction version provided + * @throws {Error} if the transaction version is unknown + * @example + * ```typescript + * const result = stark.toFeeVersion(2); + * // result = "0x100000000000000000000000000000002" + * ``` */ export function toFeeVersion(providedVersion?: BigNumberish) { if (!providedVersion) return undefined; @@ -200,6 +302,24 @@ export function toFeeVersion(providedVersion?: BigNumberish) { /** * Return provided or default v3 tx details + * @param {UniversalDetails} details details of the transaction + * @return {} an object including the V3 transaction details. + * @example + * ```typescript + * const detail: UniversalDetails = { tip: 3456n }; + * const result = stark.v3Details(detail); + * // result = { + * // tip: 3456n, + * // paymasterData: [], + * // accountDeploymentData: [], + * // nonceDataAvailabilityMode: 'L1', + * // feeDataAvailabilityMode: 'L1', + * // resourceBounds: { + * // l2_gas: { max_amount: '0x0', max_price_per_unit: '0x0' }, + * // l1_gas: { max_amount: '0x0', max_price_per_unit: '0x0' } + * // } + * // } + * ``` */ export function v3Details(details: UniversalDetails) { return { @@ -218,8 +338,15 @@ export function v3Details(details: UniversalDetails) { * V2 -> V1 * F3 -> F3 * V3 -> V3 + * @param {ETransactionVersion} providedVersion + * @returns {ETransactionVersion} if v2 then returns v1. if v3 then return v3 + * @example + * ```typescript + * const result = stark.reduceV2(constants.TRANSACTION_VERSION.V2); + * // result = "0x1" + * ``` */ -export function reduceV2(providedVersion: ETransactionVersion) { +export function reduceV2(providedVersion: ETransactionVersion): ETransactionVersion { if (providedVersion === ETransactionVersion.F2) return ETransactionVersion.F1; if (providedVersion === ETransactionVersion.V2) return ETransactionVersion.V1; return providedVersion; diff --git a/src/utils/starknetId.ts b/src/utils/starknetId.ts index f9ed7376c..73b595cac 100644 --- a/src/utils/starknetId.ts +++ b/src/utils/starknetId.ts @@ -22,8 +22,13 @@ function extractStars(str: string): [string, number] { /** * Decodes an array of BigInts into a string using the given algorithm. - * @param {bigint[]} encoded - The encoded array of BigInts. + * @param {bigint[]} encoded The encoded array of BigInts. * @return {string} The decoded string. + * @example + * ```typescript + * const result = starknetId.useDecoded([3015206943634620n]); + * // result = "starknetjs.stark" + * ``` */ export function useDecoded(encoded: bigint[]): string { let decoded = ''; @@ -69,8 +74,13 @@ export function useDecoded(encoded: bigint[]): string { /** * Encodes a string into a bigint value. * - * @param {string} decoded - The string to be encoded. - * @returns {bigint} - The encoded bigint value. + * @param {string} decoded The string to be encoded. + * @returns {bigint} The encoded bigint value. + * @example + * ```typescript + * const result = starknetId.useEncoded("starknet.js"); + * // result = 3015206943634620n + * ``` */ export function useEncoded(decoded: string): bigint { let encoded = BigInt(0); @@ -122,9 +132,14 @@ export const enum StarknetIdContract { /** * Returns the Starknet ID contract address based on the provided chain ID. * - * @param {StarknetChainId} chainId - The chain ID of the Starknet network. + * @param {StarknetChainId} chainId The chain ID of the Starknet network. * @return {string} The Starknet ID contract address. * @throws {Error} Throws an error if the Starknet ID contract is not deployed on the network. + * @example + * ```typescript + * const result = starknetId.getStarknetIdContract(constants.StarknetChainId.SN_SEPOLIA); + * // result = "0x0707f09bc576bd7cfee59694846291047e965f4184fe13dac62c56759b3b6fa7" + * ``` */ export function getStarknetIdContract(chainId: StarknetChainId): string { switch (chainId) { @@ -147,11 +162,16 @@ export const enum StarknetIdIdentityContract { /** * Returns the Starknet ID identity contract address for the given chain ID. * - * @param {StarknetChainId} chainId - The chain ID for the specified network. + * @param {StarknetChainId} chainId The chain ID for the specified network. * - * @return {string} - The Starknet ID identity contract address for the specified network. + * @return {string} The Starknet ID identity contract address for the specified network. * - * @throws {Error} - If the Starknet ID verifier contract is not deployed on the network. + * @throws {Error} If the Starknet ID verifier contract is not deployed on the network. + * @example + * ```typescript + * const result = starknetId.getStarknetIdIdentityContract(constants.StarknetChainId.SN_SEPOLIA); + * // result = "0x070DF8B4F5cb2879f8592849fA8f3134da39d25326B8558cc9C8FE8D47EA3A90" + * ``` */ export function getStarknetIdIdentityContract(chainId: StarknetChainId): string { switch (chainId) { @@ -175,6 +195,11 @@ export const StarknetIdMulticallContract = * @param {StarknetChainId} chainId - The chainId of the network. * @return {string} - The address of the Starknet.id multicall contract. * @throws {Error} - If the Starknet.id multicall contract is not deployed on the network. + * @example + * ```typescript + * const result = starknetId.getStarknetIdMulticallContract(constants.StarknetChainId.SN_SEPOLIA); + * // result = "0x034ffb8f4452df7a613a0210824d6414dbadcddce6c6e19bf4ddc9e22ce5f970" + * ``` */ export function getStarknetIdMulticallContract(chainId: StarknetChainId): string { switch (chainId) { @@ -200,6 +225,11 @@ export const enum StarknetIdVerifierContract { * @param {StarknetChainId} chainId - The ID of the Starknet chain. * @return {string} - The address of the Starknet ID Verifier contract. * @throws {Error} - If the Starknet ID Verifier contract is not deployed on the specified network. + * @example + * ```typescript + * const result = starknetId.getStarknetIdVerifierContract(constants.StarknetChainId.SN_SEPOLIA); + * // result = "0x0182EcE8173C216A395f4828e1523541b7e3600bf190CB252E1a1A0cE219d184" + * ``` */ export function getStarknetIdVerifierContract(chainId: StarknetChainId): string { switch (chainId) { @@ -225,6 +255,11 @@ export const enum StarknetIdPfpContract { * @param {StarknetChainId} chainId - The chain ID of the network. * @returns {string} - The contract address of the Starknet.id profile picture verifier contract. * @throws {Error} - Throws an error if the Starknet.id profile picture verifier contract is not yet deployed on the network. + * @example + * ```typescript + * const result = starknetId.getStarknetIdPfpContract(constants.StarknetChainId.SN_SEPOLIA); + * // result = "0x058061bb6bdc501eE215172c9f87d557C1E0f466dC498cA81b18f998Bf1362b2" + * ``` */ export function getStarknetIdPfpContract(chainId: StarknetChainId): string { switch (chainId) { @@ -252,6 +287,11 @@ export const enum StarknetIdPopContract { * @param {StarknetChainId} chainId - The chain ID of the Starknet network. * @return {string} - The Starknet ID Pop contract address. * @throws {Error} - If the Starknet ID Pop contract is not deployed on the specified network. + * @example + * ```typescript + * const result = starknetId.getStarknetIdPopContract(constants.StarknetChainId.SN_SEPOLIA); + * // result = "0x0023FE3b845ed5665a9eb3792bbB17347B490EE4090f855C1298d03BB5F49B49" + * ``` */ export function getStarknetIdPopContract(chainId: StarknetChainId): string { switch (chainId) { @@ -269,13 +309,24 @@ export function getStarknetIdPopContract(chainId: StarknetChainId): string { } /** - * Executes a method and returns a CairoCustomEnum object. + * Returns a CairoCustomEnum object. * - * Functions to build CairoCustomEnum for multicall contracts - * @param {Object} staticEx - An optional object defining the "Static" value of the CairoCustomEnum. - * @param {number[]} ifEqual - An optional array defining the "IfEqual" value of the CairoCustomEnum. - * @param {number[]} ifNotEqual - An optional array defining the "IfNotEqual" value of the CairoCustomEnum. + * Functions to build CairoCustomEnum for multiCall contracts + * @param {Object} [staticEx] An optional object defining the "Static" value of the CairoCustomEnum. + * @param {number[]} [ifEqual] An optional array defining the "IfEqual" value of the CairoCustomEnum. + * @param {number[]} [ifNotEqual] An optional array defining the "IfNotEqual" value of the CairoCustomEnum. * @return {CairoCustomEnum} - The created CairoCustomEnum object. + * @example + * ```typescript + * const result: CairoCustomEnum = starknetId.execution(undefined, [1, 2, 3], undefined); + * // result = CairoCustomEnum { + * // variant: { + * // Static: undefined, + * // IfEqual: { '0': 1, '1': 2, '2': 3 }, + * // IfNotEqual: undefined + * // } + * // } + * ``` */ export function execution( staticEx: {} | undefined, @@ -292,9 +343,16 @@ export function execution( /** * Creates a new instance of CairoCustomEnum. * - * @param {BigNumberish | undefined} hardcoded - The hardcoded value for the CairoCustomEnum. - * @param {number[] | undefined} reference - The reference array for the CairoCustomEnum. + * @param {BigNumberish} [hardcoded] The hardcoded value for the CairoCustomEnum. + * @param {number[]} [reference] The reference array for the CairoCustomEnum. * @returns {CairoCustomEnum} The new instance of CairoCustomEnum. + * @example + * ```typescript + * const result: CairoCustomEnum = starknetId.dynamicFelt(undefined, [1, 2]); + * // result = CairoCustomEnum { + * // variant: { Hardcoded: undefined, Reference: { '0': 1, '1': 2 } } + * // } + * ``` */ export function dynamicFelt( hardcoded: BigNumberish | undefined, @@ -308,10 +366,21 @@ export function dynamicFelt( /** * Creates a new instance of CairoCustomEnum with the given parameters. - * @param {BigNumberish | undefined} hardcoded - The hardcoded value. - * @param {BigNumberish[] | undefined} [reference] - The reference value (optional). - * @param {BigNumberish[] | undefined} [arrayReference] - The array reference value (optional). - * @return {CairoCustomEnum} - The new instance of CairoCustomEnum. + * @param {BigNumberish} [hardcoded] The hardcoded value. + * @param {BigNumberish[]} [reference] The reference value (optional). + * @param {BigNumberish[]} [arrayReference] The array reference value (optional). + * @return {CairoCustomEnum} The new instance of CairoCustomEnum. + * @example + * ```typescript + * const result: CairoCustomEnum = starknetId.dynamicCallData(undefined, [1, 2], undefined); + * // result = CairoCustomEnum { + * // variant: { + * // Hardcoded: undefined, + * // Reference: { '0': 1, '1': 2 }, + * // ArrayReference: undefined + * // } + * // } + * ``` */ export function dynamicCallData( hardcoded: BigNumberish | undefined, diff --git a/src/utils/transaction.ts b/src/utils/transaction.ts index 308290223..c5cadf56d 100644 --- a/src/utils/transaction.ts +++ b/src/utils/transaction.ts @@ -19,6 +19,32 @@ import { randomAddress } from './stark'; /** * Transforms a list of Calls, each with their own calldata, into * two arrays: one with the entry points, and one with the concatenated calldata + * @param {Call[]} calls the list of calls to transform. + * @returns {callArray: ParsedStruct[], calldata: BigNumberish[]} An object containing two arrays: callArray and calldata. + * @example + * ```typescript + * const calls: Call[] = [ + * { + * contractAddress: "0x1234567890123456789012345678901234567890", + * entrypoint: "functionName", + * calldata: [1,2,3] + * }, + * { + * contractAddress: "0x0987654321098765432109876543210987654321", + * entrypoint: "anotherFunction", + * calldata: [4,5,6] + * } + * ]; + * const result = transaction.transformCallsToMulticallArrays(calls); + * // result = { + * // callArray: [ + * // { to: "0x1234567890123456789012345678901234567890", selector: "1234567890", + * // data_offset: "0", data_len: "3" }, + * // { to: "0x0987654321098765432109876543210987654321", selector: "1234567890", + * // data_offset: "0987654321", data_offset: "3", data_len: "3"} + * // ], calldata: [1, 2, 3, 4, 5, 6] + * // } + * ``` */ export const transformCallsToMulticallArrays = (calls: Call[]) => { const callArray: ParsedStruct[] = []; @@ -41,6 +67,29 @@ export const transformCallsToMulticallArrays = (calls: Call[]) => { /** * Transforms a list of calls into the Cairo 0 `__execute__` calldata. + * @param {Call[]} calls the list of calls to transform + * @returns {Calldata} the Cairo 0 `__execute__` calldata + * @example + * ```typescript + * const calls: Call[] = [ + * { + * contractAddress: "0x1234567890123456789012345678901234567890", + * entrypoint: "functionName", + * calldata: [1, 2, 3] + * }, + * { + * contractAddress: "0x0987654321098765432109876543210987654321", + * entrypoint: "anotherFunction", + * calldata: [4, 5, 6] + * } + * ]; + * const result = transaction.fromCallsToExecuteCalldata(calls); + * // result = ['2', '103929005307130220006098923584552504982110632080', + * // '784552248838722632831848474045274978537388011177294206940059575485454596699', '0', + * // '3', '54400338722927882010739357306608455014511100705', + * // '836430224577382061379420368022192503799782058803937958828224424676927281484', + * // '3', '3', '6', '1', '2', '3', '4', '5', '6'] + * ``` */ export const fromCallsToExecuteCalldata = (calls: Call[]) => { const { callArray, calldata } = transformCallsToMulticallArrays(calls); @@ -50,7 +99,6 @@ export const fromCallsToExecuteCalldata = (calls: Call[]) => { /** * Transforms a list of calls into the Cairo 0 `__execute__` calldata including nonce. - * * @deprecated */ export const fromCallsToExecuteCalldataWithNonce = (calls: Call[], nonce: BigNumberish) => { @@ -59,7 +107,6 @@ export const fromCallsToExecuteCalldataWithNonce = (calls: Call[], nonce: BigNum /** * Format Data inside Calls - * * @deprecated Not required for getting execute Calldata */ export const transformCallsToMulticallArrays_cairo1 = (calls: Call[]) => { @@ -73,6 +120,29 @@ export const transformCallsToMulticallArrays_cairo1 = (calls: Call[]) => { /** * Transforms a list of calls into the Cairo 1 `__execute__` calldata. + * @param {Call[]} calls the list of calls to transform. + * @returns {Calldata} the Cairo 1 `__execute__` calldata. + * @example + * ```typescript + * const calls: Call[] = [ + * { + * contractAddress: "0x1234567890123456789012345678901234567890", + * entrypoint: "functionName", + * calldata: [1, 2, 3] + * }, + * { + * contractAddress: "0x0987654321098765432109876543210987654321", + * entrypoint: "anotherFunction", + * calldata: [4, 5, 6] + * } + * ]; + * const result = transaction.fromCallsToExecuteCalldata_cairo1(calls); + * // result = ['2', '103929005307130220006098923584552504982110632080', + * // '784552248838722632831848474045274978537388011177294206940059575485454596699', + * // '3', '1', '2', '3', '54400338722927882010739357306608455014511100705', + * // '836430224577382061379420368022192503799782058803937958828224424676927281484', + * // '3', '4', '5', '6'] + * ``` */ export const fromCallsToExecuteCalldata_cairo1 = (calls: Call[]) => { // ensure property order @@ -89,7 +159,31 @@ export const fromCallsToExecuteCalldata_cairo1 = (calls: Call[]) => { }; /** - * Create `__execute__` Calldata from Calls based on Cairo versions + * Create `__execute__` Calldata from Calls based on Cairo versions. + * @param {Call[]} calls the list of calls to transform + * @param {CairoVersion} cairoVersion the Cairo version + * @returns {Calldata} the `__execute__` calldata. + * @example + * ```typescript + * const calls: Call[] = [ + * { + * contractAddress: "0x1234567890123456789012345678901234567890", + * entrypoint: "functionName", + * calldata: [1, 2, 3] + * }, + * { + * contractAddress: "0x0987654321098765432109876543210987654321", + * entrypoint: "anotherFunction", + * calldata: [4, 5, 6] + * } + * ]; + * const result = transaction.getExecuteCalldata(calls, '1'); + * // result = ['2', '103929005307130220006098923584552504982110632080', + * // '784552248838722632831848474045274978537388011177294206940059575485454596699', + * // '3', '1', '2', '3', '54400338722927882010739357306608455014511100705', + * // '836430224577382061379420368022192503799782058803937958828224424676927281484', + * // '3', '4', '5', '6'] + * ``` */ export const getExecuteCalldata = (calls: Call[], cairoVersion: CairoVersion = '0') => { if (cairoVersion === '1') { @@ -101,10 +195,29 @@ export const getExecuteCalldata = (calls: Call[], cairoVersion: CairoVersion = ' /** * Builds a UDCCall object. * - * @param {UniversalDeployerContractPayload | UniversalDeployerContractPayload[]} payload - The payload data for the UDCCall. Can be a single payload object or an array of payload objects - *. - * @param {string} address - The address to be used in the UDCCall. - * @returns {{ calls: Array, addresses: Array }} - The UDCCall object containing an array of calls and an array of addresses. + * @param {UniversalDeployerContractPayload | UniversalDeployerContractPayload[]} payload the payload data for the UDCCall. Can be a single payload object or an array of payload objects. + * @param {string} address the address to be used in the UDCCall + * @returns { calls: Call[], addresses: string[] } the UDCCall object containing an array of calls and an array of addresses. + * @example + * ```typescript + * const payload: UniversalDeployerContractPayload = { + * classHash: "0x1234567890123456789012345678901234567890", + * salt: "0x0987654321098765432109876543210987654321", + * unique:true, + * constructorCalldata: [1, 2, 3] + * }; + * const address = "0xABCDEF1234567890ABCDEF1234567890ABCDEF12"; + * const result = transaction.buildUDCCall(payload, address); + * // result = { + * // calls: [ + * // { + * // contractAddress: "0xABCDEF1234567890ABCDEF1234567890ABCDEF12", + * // entrypoint: "functionName", + * // calldata: [classHash, salt, true, 3, 1, 2, 3] + * // }], + * // addresses: ["0x6fD084B56a7EDc5C06B3eB40f97Ae5A0C707A865"] + * // } + * ``` */ export function buildUDCCall( payload: UniversalDeployerContractPayload | UniversalDeployerContractPayload[], @@ -149,7 +262,18 @@ export function buildUDCCall( } /** - * Return transaction versions based on version type, default version type is 'transaction' + * Return transaction versions based on version type, default version type is 'transaction'. + * @param {'fee' | 'transaction'} [versionType] the type of version ("fee" or "transaction") + * @returns {v1: ETransactionVersion, v2: ETransactionVersion, v3: ETransactionVersion} an object containing the transaction versions. + * @example + * ```typescript + * const result = transaction.getVersionsByType('fee'); + * // result = { + * // v1: '0x100000000000000000000000000000001', + * // v2: '0x100000000000000000000000000000002', + * // v3: '0x100000000000000000000000000000003' + * // } + * ``` */ export function getVersionsByType(versionType?: 'fee' | 'transaction') { return versionType === 'fee' diff --git a/src/utils/uint256.ts b/src/utils/uint256.ts index 7e564bed1..d408ebe24 100644 --- a/src/utils/uint256.ts +++ b/src/utils/uint256.ts @@ -10,22 +10,46 @@ export { UINT_128_MAX, UINT_256_MAX }; /** * Convert Uint256 to bigint * Legacy support Export + * @param {Uint256} uint256 Uint256 value to convert to bigint + * @returns {bigint} BigInt representation of the input Uint256 + * @example + * ```typescript + * const uint256Value: Uint256 = {low: 1234567890, high: 1}; + * const result = uint256.uint256ToBN(uint256Value); + * // result = 340282366920938463463374607433002779346n + * ``` */ -export function uint256ToBN(uint256: Uint256) { +export function uint256ToBN(uint256: Uint256): bigint { return new CairoUint256(uint256).toBigInt(); } /** - * Test BigNumberish is smaller or equal 2**256-1 + * Test BigNumberish is in the range[0, 2**256-1] * Legacy support Export + * @param {BigNumberish} bn value to test + * @returns {boolean} True if the input value is in the range[0, 2**256-1], false otherwise + * @example + * ```typescript + * const result = uint256.isUint256(12345n); + * // result = true + * const result1 = uint256.isUint256(-1); + * // result1 = false + * ``` */ export function isUint256(bn: BigNumberish): boolean { return CairoUint256.is(bn); } /** - * Convert BigNumberish (string | number | bigint) to Uint256 (hex) + * Convert BigNumberish (string | number | bigint) to Uint256 * Legacy support Export + * @param {BigNumberish} bn value to convert to Uint256 + * @returns {Uint256} Uint256 object representing the BigNumberish value + * @example + * ```typescript + * const result = uint256.bnToUint256(1000000000n); + * // result = {"low": "0x3b9aca00", "high": "0x0"} + * ``` */ export function bnToUint256(bn: BigNumberish): Uint256 { return new CairoUint256(bn).toUint256HexString(); diff --git a/src/wallet/connect.ts b/src/wallet/connect.ts index 258c91f80..4a57d1181 100644 --- a/src/wallet/connect.ts +++ b/src/wallet/connect.ts @@ -14,7 +14,7 @@ import { /** * Request Permission for wallet account, return addresses that are allowed by user - * @param silentMode false: request user interaction allowance. true: return only pre-allowed + * @param {boolean} [silent_mode=false] false: request user interaction allowance. true: return only pre-allowed * @returns allowed accounts addresses */ export function requestAccounts(swo: StarknetWindowObject, silent_mode = false) { diff --git a/www/docs/guides/connect_network.md b/www/docs/guides/connect_network.md index e2f60b93f..9abc87917 100644 --- a/www/docs/guides/connect_network.md +++ b/www/docs/guides/connect_network.md @@ -36,8 +36,8 @@ On Starknet.js side, you have to select the proper version, to be in accordance | v0.4.0 | Starknet.js v5.21.1 | | v0.5.0 | Starknet.js v5.23.0 | | v0.5.1 | Starknet.js v5.29.0 & v6.1.0 | -| v0.6.0 | Starknet.js v6.6.6 | -| v0.7.0 | Starknet.js v6.6.6 | +| v0.6.0 | Starknet.js v6.9.0 | +| v0.7.0 | Starknet.js v6.9.0 | [!NOTE] Each Starknet.js version 6.x.x is compatible with 3 rpc spec versions, and recognize automatically the spec version if not provided. @@ -153,10 +153,10 @@ const provider = new RpcProvider({ nodeUrl: 'http://127.0.0.1:6060/v0_7' }); ## Devnet -Example of a connection to a local development node (rpc 0.6.0), with Starknet-devnet-rs: +Example of a connection to a local development node (rpc 0.7.0), with Starknet-devnet-rs v0.0.6: ```typescript const provider = new RpcProvider({ nodeUrl: 'http://127.0.0.1:5050/rpc' }); ``` -> If you have customized host and port during starknet-devnet initialization, adapt in accordance to your script. +> If you have customized host and port during starknet-devnet initialization, adapt in accordance your script. diff --git a/www/docs/guides/define_call_message.md b/www/docs/guides/define_call_message.md index 990494c39..69441e0ec 100644 --- a/www/docs/guides/define_call_message.md +++ b/www/docs/guides/define_call_message.md @@ -200,7 +200,8 @@ const myTpl = { '0': '0x0a', '1': 200 }; ### Named tuple -> [!IMPORTANT] Only for Cairo 0. +:::warning Only for Cairo 0 +::: Starknet is waiting for a list of felts. You can send to Starknet.js methods: an object, `cairo.tuple()`, list of bigNumberish. @@ -220,7 +221,9 @@ const namedTup = { min: '0x4e65ac6', max: 296735486n }; await myContract.my_function(namedTup); ``` -> [!TIP] It's not mandatory to create an object conform to the Cairo 0 named tuple, you can just use the `cairo.tuple()` function. +:::tip +It's not mandatory to create manually an object conform to the Cairo 0 named tuple ; you can just use the `cairo.tuple()` function. +::: ### Ethereum public key @@ -282,7 +285,9 @@ Const myArray = [10, "0xaa", 567n]; await myContract.my_function(myArray); ``` -> [!CAUTION] Do not add the `array_len` parameter before your array. Starknet.js will manage this element automatically. +:::danger important +Do not add the `array_len` parameter before your array. Starknet.js will manage this element automatically. +::: > It's also applicable for Cairo `Span` type. @@ -352,7 +357,9 @@ const functionName = 'my_function'; await myContract[functionName](...myParams); ``` -> [!WARNING] Objects properties have to be ordered in accordance with the ABI. +:::warning important +Objects properties have to be ordered in accordance with the ABI. +::: ### Object (without ABI conformity check) @@ -372,7 +379,9 @@ const deployResponse = await myAccount.deployContract({ This type is available for: `CallData.compile(), hash.calculateContractAddressFromHash, account.deployContract, account.deployAccount, account.execute` -> [!WARNING] Objects properties have to be ordered in accordance with the ABI. +:::warning important +Objects properties have to be ordered in accordance with the ABI. +::: ### Object (with ABI conformity check) diff --git a/www/package-lock.json b/www/package-lock.json index 448704d07..f4ab1dede 100644 --- a/www/package-lock.json +++ b/www/package-lock.json @@ -4418,9 +4418,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001566", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz", - "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==", + "version": "1.0.30001620", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001620.tgz", + "integrity": "sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==", "funding": [ { "type": "opencollective",