diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f5cb69fac..83493eb03 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -26,7 +26,7 @@ jobs: services: devnet: - image: janek2601/starknet-devnet-patched + image: shardlabs/starknet-devnet:0.3.1-seed0 ports: - 5050:5050 env: diff --git a/__tests__/account.test.ts b/__tests__/account.test.ts index 214f35bf4..0e17a5e89 100644 --- a/__tests__/account.test.ts +++ b/__tests__/account.test.ts @@ -76,11 +76,8 @@ describe('deploy and test Wallet', () => { }); test('execute with custom nonce', async () => { - const { result } = await account.callContract({ - contractAddress: account.address, - entrypoint: 'get_nonce', - }); - const nonce = toBN(result[0]).toNumber(); + const result = await account.getNonce(); + const nonce = toBN(result).toNumber(); const { transaction_hash } = await account.execute( { contractAddress: erc20Address, diff --git a/__tests__/contract.test.ts b/__tests__/contract.test.ts index aaad4814f..455a0546a 100644 --- a/__tests__/contract.test.ts +++ b/__tests__/contract.test.ts @@ -43,7 +43,6 @@ describe('class Contract {}', () => { expect(res).toHaveProperty('contractAddress'); expect(res).toHaveProperty('entrypoint'); expect(res).toHaveProperty('calldata'); - expect(res).toHaveProperty('signature'); }); test('estimate gas fee for `mint` should fail when connected to the provider', async () => { diff --git a/__tests__/defaultProvider.test.ts b/__tests__/defaultProvider.test.ts index 637ab7ba9..feef464a2 100644 --- a/__tests__/defaultProvider.test.ts +++ b/__tests__/defaultProvider.test.ts @@ -62,6 +62,11 @@ describe('defaultProvider', () => { return expect(block).toHaveProperty('block_number'); }); + test('getNonce()', async () => { + const nonce = await testProvider.getNonce(exampleContractAddress); + return expect(nonce).toEqual('0x0'); + }); + describe('getStorageAt', () => { test('with "key" type of number', () => { return expect(testProvider.getStorageAt(exampleContractAddress, 0)).resolves.not.toThrow(); diff --git a/__tests__/sequencerProvider.test.ts b/__tests__/sequencerProvider.test.ts index c5a153673..19d1bc941 100644 --- a/__tests__/sequencerProvider.test.ts +++ b/__tests__/sequencerProvider.test.ts @@ -9,12 +9,12 @@ import { // Run only if Devnet Sequencer describeIfSequencer('SequencerProvider', () => { - let provider: SequencerProvider; + let sequencerProvider: SequencerProvider; let customSequencerProvider: Provider; let exampleContractAddress: string; beforeAll(async () => { - provider = getTestProvider() as SequencerProvider; + sequencerProvider = getTestProvider() as SequencerProvider; customSequencerProvider = new Provider({ sequencer: { baseUrl: 'https://alpha4.starknet.io', @@ -28,32 +28,34 @@ describeIfSequencer('SequencerProvider', () => { let exampleTransactionHash: string; beforeAll(async () => { - const { transaction_hash, contract_address } = await provider.deployContract({ + const { transaction_hash, contract_address } = await sequencerProvider.deployContract({ contract: compiledErc20, }); - await provider.waitForTransaction(transaction_hash); + await sequencerProvider.waitForTransaction(transaction_hash); exampleTransactionHash = transaction_hash; exampleContractAddress = contract_address; }); test('getTransactionStatus()', async () => { - return expect(provider.getTransactionStatus(exampleTransactionHash)).resolves.not.toThrow(); + return expect( + sequencerProvider.getTransactionStatus(exampleTransactionHash) + ).resolves.not.toThrow(); }); test('transaction trace', async () => { - const transactionTrace = await provider.getTransactionTrace(exampleTransactionHash); + const transactionTrace = await sequencerProvider.getTransactionTrace(exampleTransactionHash); expect(transactionTrace).toHaveProperty('function_invocation'); expect(transactionTrace).toHaveProperty('signature'); }); test('getCode() -> { bytecode }', async () => { - const code = await provider.getCode(exampleContractAddress); + const code = await sequencerProvider.getCode(exampleContractAddress); return expect(Array.isArray(code.bytecode)).toBe(true); }); describeIfNotDevnet('which are not available on devnet', () => { test('getContractAddresses()', async () => { - const { GpsStatementVerifier, Starknet } = await provider.getContractAddresses(); + const { GpsStatementVerifier, Starknet } = await sequencerProvider.getContractAddresses(); expect(typeof GpsStatementVerifier).toBe('string'); expect(typeof Starknet).toBe('string'); }); diff --git a/__tests__/utils/ellipticalCurve.test.ts b/__tests__/utils/ellipticalCurve.test.ts index 2bba8d4ec..3a3e5c5a1 100644 --- a/__tests__/utils/ellipticalCurve.test.ts +++ b/__tests__/utils/ellipticalCurve.test.ts @@ -2,9 +2,8 @@ import { StarknetChainId } from '../../src/constants'; import { ec, getKeyPair, getStarkKey, sign, verify } from '../../src/utils/ellipticCurve'; import { removeHexPrefix } from '../../src/utils/encode'; import { - calculcateTransactionHash, + calculateTransactionHash, computeHashOnElements, - getSelectorFromName, pedersen, transactionVersion, } from '../../src/utils/hash'; @@ -57,25 +56,25 @@ test('hashMessage()', () => { const maxFee = '0'; const calldata = fromCallsToExecuteCalldataWithNonce(transactions, nonce); - const hashMsg = calculcateTransactionHash( + const hashMsg = calculateTransactionHash( account, transactionVersion, - getSelectorFromName('__execute__'), calldata, maxFee, - StarknetChainId.TESTNET + StarknetChainId.TESTNET, + nonce ); expect(hashMsg).toMatchInlineSnapshot( - `"0x4c337c6bf32b2cf2b8ae54064e4b982c214660e8d0423b431a3fde10b9b9c02"` + `"0x6d1706bd3d1ba7c517be2a2a335996f63d4738e2f182144d078a1dd9997062e"` ); const keyPair = getKeyPair(privateKey); const [r, s] = sign(keyPair, removeHexPrefix(hashMsg)); expect(r.toString()).toMatchInlineSnapshot( - `"1944132633844378384908742523072599391732300777648030785844673145513474741467"` + `"1427981024487605678086498726488552139932400435436186597196374630267616399345"` ); expect(s.toString()).toMatchInlineSnapshot( - `"1067771353159635307522498807851959257107695451405842425488451092336556917559"` + `"1853664302719670721837677288395394946745467311923401353018029119631574115563"` ); }); diff --git a/src/account/default.ts b/src/account/default.ts index 28523d067..d5eaebeea 100644 --- a/src/account/default.ts +++ b/src/account/default.ts @@ -1,6 +1,7 @@ import { ZERO } from '../constants'; import { ProviderInterface, ProviderOptions } from '../provider'; import { Provider } from '../provider/default'; +import { BlockIdentifier } from '../provider/utils'; import { Signer, SignerInterface } from '../signer'; import { Abi, @@ -12,10 +13,10 @@ import { Signature, } from '../types'; import { EstimateFee, EstimateFeeDetails } from '../types/account'; -import { feeTransactionVersion, transactionVersion } from '../utils/hash'; -import { BigNumberish, toBN, toHex } from '../utils/number'; +import { transactionVersion } from '../utils/hash'; +import { BigNumberish, toBN } from '../utils/number'; import { compileCalldata, estimatedFeeToMaxFee } from '../utils/stark'; -import { fromCallsToExecuteCalldataWithNonce } from '../utils/transaction'; +import { fromCallsToExecuteCalldata } from '../utils/transaction'; import { TypedData, getMessageHash } from '../utils/typedData'; import { AccountInterface } from './interface'; @@ -32,12 +33,8 @@ export class Account extends Provider implements AccountInterface { 'getPubKey' in keyPairOrSigner ? keyPairOrSigner : new Signer(keyPairOrSigner as KeyPair); } - public async getNonce(): Promise { - const { result } = await this.callContract({ - contractAddress: this.address, - entrypoint: 'get_nonce', - }); - return toHex(toBN(result[0])); + public async getNonce(blockIdentifier?: BlockIdentifier): Promise { + return super.getNonce(this.address, blockIdentifier); } public async estimateFee( @@ -45,13 +42,13 @@ export class Account extends Provider implements AccountInterface { { nonce: providedNonce, blockIdentifier }: EstimateFeeDetails = {} ): Promise { const transactions = Array.isArray(calls) ? calls : [calls]; - const nonce = providedNonce ?? (await this.getNonce()); - const version = toBN(feeTransactionVersion); + const nonce = toBN(providedNonce ?? (await this.getNonce())); + const version = toBN(transactionVersion); const chainId = await this.getChainId(); const signerDetails: InvocationsSignerDetails = { walletAddress: this.address, - nonce: toBN(nonce), + nonce, maxFee: ZERO, version, chainId, @@ -59,11 +56,11 @@ export class Account extends Provider implements AccountInterface { const signature = await this.signer.signTransaction(transactions, signerDetails); - const calldata = fromCallsToExecuteCalldataWithNonce(transactions, nonce); + const calldata = fromCallsToExecuteCalldata(transactions); const response = await super.getEstimateFee( - { contractAddress: this.address, entrypoint: '__execute__', calldata, signature }, - blockIdentifier, - { version } + { contractAddress: this.address, calldata, signature }, + { version, nonce }, + blockIdentifier ); const suggestedMaxFee = estimatedFeeToMaxFee(response.overall_fee); @@ -112,11 +109,12 @@ export class Account extends Provider implements AccountInterface { const signature = await this.signer.signTransaction(transactions, signerDetails, abis); - const calldata = fromCallsToExecuteCalldataWithNonce(transactions, nonce); + const calldata = fromCallsToExecuteCalldata(transactions); return this.invokeFunction( - { contractAddress: this.address, entrypoint: '__execute__', calldata, signature }, + { contractAddress: this.address, calldata, signature }, { + nonce, maxFee, version, } @@ -158,7 +156,7 @@ export class Account extends Provider implements AccountInterface { try { await this.callContract({ contractAddress: this.address, - entrypoint: 'is_valid_signature', + entrypoint: 'isValidSignature', calldata: compileCalldata({ hash: toBN(hash).toString(), signature: signature.map((x) => toBN(x).toString()), diff --git a/src/account/interface.ts b/src/account/interface.ts index 6ca606c85..6bb8738a7 100644 --- a/src/account/interface.ts +++ b/src/account/interface.ts @@ -1,4 +1,5 @@ import { ProviderInterface } from '../provider'; +import { BlockIdentifier } from '../provider/utils'; import { SignerInterface } from '../signer'; import { Abi, @@ -92,5 +93,5 @@ export abstract class AccountInterface extends ProviderInterface { */ public abstract verifyMessageHash(hash: BigNumberish, signature: Signature): Promise; - public abstract getNonce(): Promise; + public abstract getNonce(blockIdentifier?: BlockIdentifier): Promise; } diff --git a/src/contract/default.ts b/src/contract/default.ts index a46f99d9f..0f70fdee2 100644 --- a/src/contract/default.ts +++ b/src/contract/default.ts @@ -9,10 +9,10 @@ import { AbiEntry, Args, AsyncContractFunction, + Call, Calldata, ContractFunction, FunctionAbi, - Invocation, InvokeFunctionResponse, Overrides, ParsedStruct, @@ -578,13 +578,22 @@ export class Contract implements ContractInterface { }); } + if (!options.nonce) { + throw new Error(`Nonce is required when invoking a function without an account`); + } + // eslint-disable-next-line no-console console.warn(`Invoking ${method} without an account. This will not work on a public node.`); - return this.providerOrAccount.invokeFunction({ - ...invocation, - signature: options.signature || [], - }); + return this.providerOrAccount.invokeFunction( + { + ...invocation, + signature: options.signature || [], + }, + { + nonce: options.nonce, + } + ); } public async call( @@ -630,13 +639,12 @@ export class Contract implements ContractInterface { throw Error('Contract must be connected to the account contract to estimate'); } - public populate(method: string, args: Array = []): Invocation { + public populate(method: string, args: Array = []): Call { const { inputs } = this.abi.find((abi) => abi.name === method) as FunctionAbi; return { contractAddress: this.address, entrypoint: method, calldata: this.compileCalldata(args, inputs), - signature: [], }; } } diff --git a/src/provider/default.ts b/src/provider/default.ts index 8b1584eb9..b5d51554c 100644 --- a/src/provider/default.ts +++ b/src/provider/default.ts @@ -13,7 +13,7 @@ import { GetTransactionReceiptResponse, GetTransactionResponse, Invocation, - InvocationsDetails, + InvocationsDetailsWithNonce, InvokeFunctionResponse, } from '../types'; import { BigNumberish } from '../utils/number'; @@ -63,10 +63,17 @@ export class Provider implements ProviderInterface { public async getEstimateFee( invocation: Invocation, - blockIdentifier: BlockIdentifier = 'pending', - invocationDetails: InvocationsDetails = {} + invocationDetails: InvocationsDetailsWithNonce, + blockIdentifier: BlockIdentifier = 'pending' ): Promise { - return this.provider.getEstimateFee(invocation, blockIdentifier, invocationDetails); + return this.provider.getEstimateFee(invocation, invocationDetails, blockIdentifier); + } + + public async getNonce( + contractAddress: string, + blockIdentifier?: BlockIdentifier + ): Promise { + return this.provider.getNonce(contractAddress, blockIdentifier); } public async getStorageAt( @@ -94,7 +101,7 @@ export class Provider implements ProviderInterface { public async invokeFunction( functionInvocation: Invocation, - details: InvocationsDetails + details: InvocationsDetailsWithNonce ): Promise { return this.provider.invokeFunction(functionInvocation, details); } diff --git a/src/provider/interface.ts b/src/provider/interface.ts index e5528ff6c..86278b3e3 100644 --- a/src/provider/interface.ts +++ b/src/provider/interface.ts @@ -13,7 +13,7 @@ import type { GetTransactionReceiptResponse, GetTransactionResponse, Invocation, - InvocationsDetails, + InvocationsDetailsWithNonce, InvokeFunctionResponse, } from '../types'; import type { BigNumberish } from '../utils/number'; @@ -69,6 +69,17 @@ export abstract class ProviderInterface { blockIdentifier?: BlockIdentifier ): Promise; + /** + * Gets the nonce of a contract with respect to a specific block + * + * @param contractAddress - contract address + * @returns the hex nonce + */ + public abstract getNonce( + contractAddress: string, + blockIdentifier?: BlockIdentifier + ): Promise; + /** * Gets the contract's storage variable at a specific key. * @@ -141,7 +152,7 @@ export abstract class ProviderInterface { */ public abstract invokeFunction( invocation: Invocation, - details?: InvocationsDetails + details: InvocationsDetailsWithNonce ): Promise; /** @@ -160,8 +171,8 @@ export abstract class ProviderInterface { */ public abstract getEstimateFee( invocation: Invocation, - blockIdentifier: BlockIdentifier, - details?: InvocationsDetails + details: InvocationsDetailsWithNonce, + blockIdentifier: BlockIdentifier ): Promise; /** diff --git a/src/provider/rpc.ts b/src/provider/rpc.ts index 346032850..1aae7f8b0 100644 --- a/src/provider/rpc.ts +++ b/src/provider/rpc.ts @@ -12,7 +12,7 @@ import { GetTransactionReceiptResponse, GetTransactionResponse, Invocation, - InvocationsDetails, + InvocationsDetailsWithNonce, InvokeFunctionResponse, } from '../types'; import { RPC } from '../types/api'; @@ -118,8 +118,15 @@ export class RpcProvider implements ProviderInterface { return this.fetchEndpoint('starknet_getClassHashAt', [block.identifier, contractAddress]); } - public async getNonce(contractAddress: string): Promise { - return this.fetchEndpoint('starknet_getNonce', [contractAddress]); + public async getNonce( + contractAddress: string, + blockIdentifier: BlockIdentifier = 'pending' + ): Promise { + const blockIdentifierGetter = new Block(blockIdentifier); + return this.fetchEndpoint('starknet_getNonce', [ + contractAddress, + blockIdentifierGetter.identifier(), + ]); } public async getPendingTransactions(): Promise { @@ -195,13 +202,12 @@ export class RpcProvider implements ProviderInterface { public async getEstimateFee( invocation: Invocation, - blockIdentifier: BlockIdentifier = 'pending', - invocationDetails: InvocationsDetails = {} + invocationDetails: InvocationsDetailsWithNonce, + blockIdentifier: BlockIdentifier = 'pending' ): Promise { return this.fetchEndpoint('starknet_estimateFee', [ { contract_address: invocation.contractAddress, - entry_point_selector: getSelectorFromName(invocation.entrypoint), calldata: parseCalldata(invocation.calldata), signature: bigNumberishArrayToHexadecimalStringArray(invocation.signature || []), version: toHex(toBN(invocationDetails?.version || 0)), @@ -246,12 +252,11 @@ export class RpcProvider implements ProviderInterface { public async invokeFunction( functionInvocation: Invocation, - details: InvocationsDetails + details: InvocationsDetailsWithNonce ): Promise { return this.fetchEndpoint('starknet_addInvokeTransaction', [ { contract_address: functionInvocation.contractAddress, - entry_point_selector: getSelectorFromName(functionInvocation.entrypoint), calldata: parseCalldata(functionInvocation.calldata), }, bigNumberishArrayToHexadecimalStringArray(functionInvocation.signature || []), diff --git a/src/provider/sequencer.ts b/src/provider/sequencer.ts index 51a209fab..576d63f35 100644 --- a/src/provider/sequencer.ts +++ b/src/provider/sequencer.ts @@ -14,7 +14,7 @@ import { GetTransactionReceiptResponse, GetTransactionResponse, Invocation, - InvocationsDetails, + InvocationsDetailsWithNonce, InvokeFunctionResponse, } from '../types'; import { @@ -234,6 +234,13 @@ export class SequencerProvider implements ProviderInterface { ); } + public async getNonce( + contractAddress: string, + blockIdentifier: BlockIdentifier = 'pending' + ): Promise { + return this.fetchEndpoint('get_nonce', { contractAddress, blockIdentifier }); + } + public async getStorageAt( contractAddress: string, key: BigNumberish, @@ -272,16 +279,16 @@ export class SequencerProvider implements ProviderInterface { public async invokeFunction( functionInvocation: Invocation, - details: InvocationsDetails + details: InvocationsDetailsWithNonce ): Promise { return this.fetchEndpoint('add_transaction', undefined, { type: 'INVOKE_FUNCTION', contract_address: functionInvocation.contractAddress, - entry_point_selector: getSelectorFromName(functionInvocation.entrypoint), calldata: bigNumberishArrayToDecimalStringArray(functionInvocation.calldata ?? []), signature: bigNumberishArrayToDecimalStringArray(functionInvocation.signature ?? []), + nonce: toHex(toBN(details.nonce)), max_fee: toHex(toBN(details.maxFee || 0)), - version: toHex(toBN(details.version || 0)), + version: toHex(toBN(details.version || 1)), }).then(this.responseParser.parseInvokeFunctionResponse); } @@ -316,18 +323,19 @@ export class SequencerProvider implements ProviderInterface { public async getEstimateFee( invocation: Invocation, - blockIdentifier: BlockIdentifier = 'pending', - invocationDetails: InvocationsDetails = {} + invocationDetails: InvocationsDetailsWithNonce, + blockIdentifier: BlockIdentifier = 'pending' ): Promise { return this.fetchEndpoint( 'estimate_fee', { blockIdentifier }, { + type: 'INVOKE_FUNCTION', contract_address: invocation.contractAddress, - entry_point_selector: getSelectorFromName(invocation.entrypoint), calldata: invocation.calldata ?? [], signature: bigNumberishArrayToDecimalStringArray(invocation.signature || []), - version: toHex(toBN(invocationDetails?.version || 0)), + version: toHex(toBN(invocationDetails?.version || 1)), + nonce: toHex(toBN(invocationDetails.nonce)), } ).then(this.responseParser.parseFeeEstimateResponse); } diff --git a/src/signer/default.ts b/src/signer/default.ts index 464f53562..0bf08a408 100644 --- a/src/signer/default.ts +++ b/src/signer/default.ts @@ -1,7 +1,7 @@ -import { Abi, Invocation, InvocationsSignerDetails, KeyPair, Signature } from '../types'; +import { Abi, Call, InvocationsSignerDetails, KeyPair, Signature } from '../types'; import { genKeyPair, getStarkKey, sign } from '../utils/ellipticCurve'; -import { calculcateTransactionHash, getSelectorFromName } from '../utils/hash'; -import { fromCallsToExecuteCalldataWithNonce } from '../utils/transaction'; +import { calculateTransactionHash } from '../utils/hash'; +import { fromCallsToExecuteCalldata } from '../utils/transaction'; import { TypedData, getMessageHash } from '../utils/typedData'; import { SignerInterface } from './interface'; @@ -17,7 +17,7 @@ export class Signer implements SignerInterface { } public async signTransaction( - transactions: Invocation[], + transactions: Call[], transactionsDetail: InvocationsSignerDetails, abis?: Abi[] ): Promise { @@ -26,15 +26,15 @@ export class Signer implements SignerInterface { } // now use abi to display decoded data somewhere, but as this signer is headless, we can't do that - const calldata = fromCallsToExecuteCalldataWithNonce(transactions, transactionsDetail.nonce); + const calldata = fromCallsToExecuteCalldata(transactions); - const msgHash = calculcateTransactionHash( + const msgHash = calculateTransactionHash( transactionsDetail.walletAddress, transactionsDetail.version, - getSelectorFromName('__execute__'), calldata, transactionsDetail.maxFee, - transactionsDetail.chainId + transactionsDetail.chainId, + transactionsDetail.nonce ); return sign(this.keyPair, msgHash); diff --git a/src/signer/interface.ts b/src/signer/interface.ts index 83cff189c..d9c9ee208 100644 --- a/src/signer/interface.ts +++ b/src/signer/interface.ts @@ -1,4 +1,4 @@ -import { Abi, Invocation, InvocationsSignerDetails, Signature } from '../types'; +import { Abi, Call, InvocationsSignerDetails, Signature } from '../types'; import { TypedData } from '../utils/typedData'; export abstract class SignerInterface { @@ -33,7 +33,7 @@ export abstract class SignerInterface { * @returns signature */ public abstract signTransaction( - transactions: Invocation[], + transactions: Call[], transactionsDetail: InvocationsSignerDetails, abis?: Abi[] ): Promise; diff --git a/src/types/api/sequencer.ts b/src/types/api/sequencer.ts index 4bf867f38..ab951db9f 100644 --- a/src/types/api/sequencer.ts +++ b/src/types/api/sequencer.ts @@ -95,9 +95,8 @@ export namespace Sequencer { contract_address: string; signature?: Signature; entry_point_type?: EntryPointType; - entry_point_selector: string; calldata?: RawCalldata; - nonce?: BigNumberish; + nonce: BigNumberish; max_fee?: BigNumberish; version?: BigNumberish; }; @@ -118,6 +117,7 @@ export namespace Sequencer { export interface InvokeFunctionTransactionResponse extends InvokeFunctionTransaction { transaction_hash: string; + entry_point_selector: string; } export type TransactionResponse = @@ -202,12 +202,17 @@ export namespace Sequencer { export type CallContractTransaction = Omit< InvokeFunctionTransaction, 'type' | 'entry_point_type' | 'nonce' - >; + > & { entry_point_selector: string }; export type CallContractResponse = { result: string[]; }; + export type EstimateFeeTransaction = Omit< + InvokeFunctionTransaction, + 'max_fee' | 'entry_point_type' + >; + // Support 0.9.1 changes in a backward-compatible way export type EstimateFeeResponse = | { @@ -259,6 +264,14 @@ export namespace Sequencer { REQUEST: never; RESPONSE: TransactionReceiptResponse; }; + get_nonce: { + QUERY: { + contractAddress: string; + blockIdentifier: BlockIdentifier; + }; + REQUEST: never; + RESPONSE: BigNumberish; + }; get_storage_at: { QUERY: { contractAddress: string; @@ -294,7 +307,7 @@ export namespace Sequencer { QUERY: { blockIdentifier: BlockIdentifier; }; - REQUEST: CallContractTransaction; + REQUEST: EstimateFeeTransaction; RESPONSE: EstimateFeeResponse; }; get_class_by_hash: { diff --git a/src/types/lib.ts b/src/types/lib.ts index c9b4b8c36..71272d760 100644 --- a/src/types/lib.ts +++ b/src/types/lib.ts @@ -17,14 +17,14 @@ export type DeclareContractPayload = { version?: BigNumberish; }; -export type Invocation = { +export type CallDetails = { contractAddress: string; - entrypoint: string; calldata?: RawCalldata; - signature?: Signature; }; -export type Call = Omit; +export type Invocation = CallDetails & { signature?: Signature }; + +export type Call = CallDetails & { entrypoint: string }; export type InvocationsDetails = { nonce?: BigNumberish; @@ -32,6 +32,8 @@ export type InvocationsDetails = { version?: BigNumberish; }; +export type InvocationsDetailsWithNonce = InvocationsDetails & { nonce: BigNumberish }; + export type Status = | 'NOT_RECEIVED' | 'RECEIVED' diff --git a/src/utils/hash.ts b/src/utils/hash.ts index c9f6dab69..3c295c67b 100644 --- a/src/utils/hash.ts +++ b/src/utils/hash.ts @@ -17,7 +17,7 @@ import { ec } from './ellipticCurve'; import { addHexPrefix, buf2hex, removeHexPrefix, utf8ToArray } from './encode'; import { BigNumberish, toBN, toFelt, toHex } from './number'; -export const transactionVersion = 0; +export const transactionVersion = 1; export const feeTransactionVersion = toBN(2).pow(toBN(128)).add(toBN(transactionVersion)); export function keccakBn(value: BigNumberish): string { @@ -124,22 +124,23 @@ export function calculateDeployTransactionHash( ); } -export function calculcateTransactionHash( +export function calculateTransactionHash( contractAddress: BigNumberish, version: BigNumberish, - entryPointSelector: BigNumberish, calldata: BigNumberish[], maxFee: BigNumberish, - chainId: StarknetChainId + chainId: StarknetChainId, + nonce: BigNumberish ): string { return calculateTransactionHashCommon( TransactionHashPrefix.INVOKE, version, contractAddress, - entryPointSelector, + 0, calldata, maxFee, - chainId + chainId, + [nonce] ); } diff --git a/src/utils/responseParser/rpc.ts b/src/utils/responseParser/rpc.ts index 13d655006..ee490f68e 100644 --- a/src/utils/responseParser/rpc.ts +++ b/src/utils/responseParser/rpc.ts @@ -45,7 +45,6 @@ export class RPCResponseParser extends ResponseParser { return { calldata: res.calldata || [], contract_address: res.contract_address, - entry_point_selector: res.entry_point_selector, max_fee: res.max_fee, nonce: res.nonce, signature: res.signature || [], diff --git a/www/docs/API/account.md b/www/docs/API/account.md index 8045c5ee2..45b2c055b 100644 --- a/www/docs/API/account.md +++ b/www/docs/API/account.md @@ -24,9 +24,9 @@ The address of the account contract. ## Methods -account.**getNonce()** => _Promise < string >_ +account.**getNonce()** => _Promise < BigNumberish >_ -Gets the new Nonce for the next transaction. +Gets the new Nonce of the connected account for the next transaction.
@@ -59,7 +59,7 @@ The _transactionsDetail_ object may include any of: - transactionsDetail.**maxFee** - Max Fee that that will be used to execute the call(s) - transactionsDetail.**nonce** - Nonce for the transaction -- transactionsDetail.**version** - Version for the transaction (default is 0) +- transactionsDetail.**version** - Version for the transaction (default is 1) ###### _AddTransactionResponse_ diff --git a/www/docs/API/contract.md b/www/docs/API/contract.md index e0154075c..78effab46 100644 --- a/www/docs/API/contract.md +++ b/www/docs/API/contract.md @@ -78,8 +78,8 @@ contract.estimateGas.**METHOD_NAME**( ...args ) => _Promise < EstimateFeeRespons Returns the estimate units of gas that would be required to execute the METHOD_NAME with args and overrides. -contract.populateTransaction.**METHOD_NAME**( ...args [ , overrides ] ) ⇒ _Invocation_ +contract.populateTransaction.**METHOD_NAME**( ...args [ , overrides ] ) ⇒ _Call_ -Returns an _Invocation_ object which represents the transaction that would need to be signed and submitted to the network to execute METHOD_NAME with args and overrides. +Returns an _Call_ object which represents the transaction that would need to be signed and submitted to the network to execute METHOD_NAME with args and overrides. The overrides are identical to the overrides above for write methods. diff --git a/www/docs/API/provider.md b/www/docs/API/provider.md index b55cbfe7c..45b6b514c 100644 --- a/www/docs/API/provider.md +++ b/www/docs/API/provider.md @@ -319,6 +319,12 @@ Gets the latest block number.
+provider.**getNonce**(contractAddress, blockIdentifier) => _Promise < BigNumberish >_ + +Gets the nonce of the provided contractAddress + +
+ provider.**getSyncingStats**() => _Promise < GetSyncingStatsResponse >_ Gets syncing status of the node. diff --git a/www/docs/API/utils.md b/www/docs/API/utils.md index a1520c201..8b0f8f29d 100644 --- a/www/docs/API/utils.md +++ b/www/docs/API/utils.md @@ -268,9 +268,9 @@ Function that calculates the deployment transaction hash in the StarkNet network Internally calls `calculateTransactionHashCommon` with `TransactionHashPrefix.DEPLOY`. -### calculcateTransactionHash +### calculateTransactionHash -`calculcateTransactionHash(contractAddress: BigNumberish, version: BigNumberish, entryPointSelector: BigNumberish, calldata: BigNumberish[], maxFee: BigNumberish, chainId: StarknetChainId): string` +`calculateTransactionHash(contractAddress: BigNumberish, version: BigNumberish, entryPointSelector: BigNumberish, calldata: BigNumberish[], maxFee: BigNumberish, chainId: StarknetChainId, nonce: BigNumberish): string` Function that internally calls `calculateTransactionHashCommon`, with `TransactionHashPrefix.INVOKE`.