Skip to content

Commit

Permalink
Support Sepolia network; Support starknet_chainId endpoint (#137)
Browse files Browse the repository at this point in the history
  • Loading branch information
DelevoXDG authored Feb 6, 2024
1 parent 3f1ef27 commit ad1cd44
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 77 deletions.
2 changes: 1 addition & 1 deletion Examples/StarknetDemo/StarknetDemo/AccountsStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class AccountsStore: ObservableObject {

init() {
// Create starknet provider that will be used to communicate with the given starknet node.
self.provider = StarknetProvider(starknetChainId: .testnet, url: rpcEndpoint)!
self.provider = StarknetProvider(url: rpcEndpoint)!

// Create a signer that will be used to sign starknet transactions with provided private key.
let account1Signer = StarkCurveSigner(privateKey: account1PrivateKey)!
Expand Down
32 changes: 18 additions & 14 deletions Sources/Starknet/Accounts/StarknetAccount.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,44 +40,48 @@ public class StarknetAccount: StarknetAccountProtocol {
StarknetDeployAccountTransactionV3(signature: signature, l1ResourceBounds: params.resourceBounds.l1Gas, nonce: params.nonce, contractAddressSalt: salt, constructorCalldata: calldata, classHash: classHash, forFeeEstimation: forFeeEstimation)
}

public func signV1(calls: [StarknetCall], params: StarknetInvokeParamsV1, forFeeEstimation: Bool) throws -> StarknetInvokeTransactionV1 {
public func signV1(calls: [StarknetCall], params: StarknetInvokeParamsV1, forFeeEstimation: Bool) async throws -> StarknetInvokeTransactionV1 {
let calldata = starknetCallsToExecuteCalldata(calls: calls, cairoVersion: cairoVersion)

let transaction = makeInvokeTransactionV1(calldata: calldata, signature: [], params: params, forFeeEstimation: forFeeEstimation)

let hash = StarknetTransactionHashCalculator.computeHash(of: transaction, chainId: provider.starknetChainId)
let chainId = try await provider.getChainId()
let hash = StarknetTransactionHashCalculator.computeHash(of: transaction, chainId: chainId)

let signature = try signer.sign(transactionHash: hash)

return makeInvokeTransactionV1(calldata: calldata, signature: signature, params: params, forFeeEstimation: forFeeEstimation)
}

public func signV3(calls: [StarknetCall], params: StarknetInvokeParamsV3, forFeeEstimation: Bool) throws -> StarknetInvokeTransactionV3 {
public func signV3(calls: [StarknetCall], params: StarknetInvokeParamsV3, forFeeEstimation: Bool) async throws -> StarknetInvokeTransactionV3 {
let calldata = starknetCallsToExecuteCalldata(calls: calls, cairoVersion: cairoVersion)

let transaction = makeInvokeTransactionV3(calldata: calldata, signature: [], params: params, forFeeEstimation: forFeeEstimation)

let hash = StarknetTransactionHashCalculator.computeHash(of: transaction, chainId: provider.starknetChainId)
let chainId = try await provider.getChainId()
let hash = StarknetTransactionHashCalculator.computeHash(of: transaction, chainId: chainId)

let signature = try signer.sign(transactionHash: hash)

return makeInvokeTransactionV3(calldata: calldata, signature: signature, params: params, forFeeEstimation: forFeeEstimation)
}

public func signDeployAccountV1(classHash: Felt, calldata: StarknetCalldata, salt: Felt, params: StarknetDeployAccountParamsV1, forFeeEstimation: Bool) throws -> StarknetDeployAccountTransactionV1 {
public func signDeployAccountV1(classHash: Felt, calldata: StarknetCalldata, salt: Felt, params: StarknetDeployAccountParamsV1, forFeeEstimation: Bool) async throws -> StarknetDeployAccountTransactionV1 {
let transaction = makeDeployAccountTransactionV1(classHash: classHash, salt: salt, calldata: calldata, signature: [], params: params, forFeeEstimation: forFeeEstimation)

let hash = StarknetTransactionHashCalculator.computeHash(of: transaction, chainId: provider.starknetChainId)
let chainId = try await provider.getChainId()
let hash = StarknetTransactionHashCalculator.computeHash(of: transaction, chainId: chainId)

let signature = try signer.sign(transactionHash: hash)

return makeDeployAccountTransactionV1(classHash: classHash, salt: salt, calldata: calldata, signature: signature, params: params, forFeeEstimation: forFeeEstimation)
}

public func signDeployAccountV3(classHash: Felt, calldata: StarknetCalldata, salt: Felt, params: StarknetDeployAccountParamsV3, forFeeEstimation: Bool) throws -> StarknetDeployAccountTransactionV3 {
public func signDeployAccountV3(classHash: Felt, calldata: StarknetCalldata, salt: Felt, params: StarknetDeployAccountParamsV3, forFeeEstimation: Bool) async throws -> StarknetDeployAccountTransactionV3 {
let transaction = makeDeployAccountTransactionV3(classHash: classHash, salt: salt, calldata: calldata, signature: [], params: params, forFeeEstimation: forFeeEstimation)

let hash = StarknetTransactionHashCalculator.computeHash(of: transaction, chainId: provider.starknetChainId)
let chainId = try await provider.getChainId()
let hash = StarknetTransactionHashCalculator.computeHash(of: transaction, chainId: chainId)

let signature = try signer.sign(transactionHash: hash)

Expand All @@ -102,7 +106,7 @@ public class StarknetAccount: StarknetAccountProtocol {
}

let params = StarknetInvokeParamsV1(nonce: nonce, maxFee: maxFee)
let signedTransaction = try signV1(calls: calls, params: params, forFeeEstimation: false)
let signedTransaction = try await signV1(calls: calls, params: params, forFeeEstimation: false)

return try await provider.addInvokeTransaction(signedTransaction)
}
Expand All @@ -125,35 +129,35 @@ public class StarknetAccount: StarknetAccountProtocol {
}

let params = StarknetInvokeParamsV3(nonce: nonce, l1ResourceBounds: resourceBounds.l1Gas)
let signedTransaction = try signV3(calls: calls, params: params, forFeeEstimation: false)
let signedTransaction = try await signV3(calls: calls, params: params, forFeeEstimation: false)

return try await provider.addInvokeTransaction(signedTransaction)
}

public func estimateFeeV1(calls: [StarknetCall], nonce: Felt, skipValidate: Bool) async throws -> StarknetFeeEstimate {
let params = StarknetInvokeParamsV1(nonce: nonce, maxFee: .zero)
let signedTransaction = try signV1(calls: calls, params: params, forFeeEstimation: true)
let signedTransaction = try await signV1(calls: calls, params: params, forFeeEstimation: true)

return try await provider.estimateFee(for: signedTransaction, simulationFlags: skipValidate ? [.skipValidate] : [])
}

public func estimateFeeV3(calls: [StarknetCall], nonce: Felt, skipValidate: Bool) async throws -> StarknetFeeEstimate {
let params = StarknetInvokeParamsV3(nonce: nonce, l1ResourceBounds: .zero)
let signedTransaction = try signV3(calls: calls, params: params, forFeeEstimation: true)
let signedTransaction = try await signV3(calls: calls, params: params, forFeeEstimation: true)

return try await provider.estimateFee(for: signedTransaction, simulationFlags: skipValidate ? [.skipValidate] : [])
}

public func estimateDeployAccountFeeV1(classHash: Felt, calldata: StarknetCalldata, salt: Felt, nonce: Felt, skipValidate: Bool) async throws -> StarknetFeeEstimate {
let params = StarknetDeployAccountParamsV1(nonce: nonce, maxFee: 0)
let signedTransaction = try signDeployAccountV1(classHash: classHash, calldata: calldata, salt: salt, params: params, forFeeEstimation: true)
let signedTransaction = try await signDeployAccountV1(classHash: classHash, calldata: calldata, salt: salt, params: params, forFeeEstimation: true)

return try await provider.estimateFee(for: signedTransaction, simulationFlags: skipValidate ? [.skipValidate] : [])
}

public func estimateDeployAccountFeeV3(classHash: Felt, calldata: StarknetCalldata, salt: Felt, nonce: Felt, skipValidate: Bool) async throws -> StarknetFeeEstimate {
let params = StarknetDeployAccountParamsV3(nonce: nonce, l1ResourceBounds: .zero)
let signedTransaction = try signDeployAccountV3(classHash: classHash, calldata: calldata, salt: salt, params: params, forFeeEstimation: true)
let signedTransaction = try await signDeployAccountV3(classHash: classHash, calldata: calldata, salt: salt, params: params, forFeeEstimation: true)

return try await provider.estimateFee(for: signedTransaction, simulationFlags: skipValidate ? [.skipValidate] : [])
}
Expand Down
34 changes: 17 additions & 17 deletions Sources/Starknet/Accounts/StarknetAccountProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public protocol StarknetAccountProtocol {
/// - forFeeEstimation: Flag indicating whether the different version of transaction should be used; such transaction can only be used for fee estimation
///
/// - Returns: Signed invoke v1 transaction
func signV1(calls: [StarknetCall], params: StarknetInvokeParamsV1, forFeeEstimation: Bool) throws -> StarknetInvokeTransactionV1
func signV1(calls: [StarknetCall], params: StarknetInvokeParamsV1, forFeeEstimation: Bool) async throws -> StarknetInvokeTransactionV1

/// Sign list of calls as invoke transaction v3
///
Expand All @@ -22,7 +22,7 @@ public protocol StarknetAccountProtocol {
/// - forFeeEstimation: Flag indicating whether the different version of transaction should be used; such transaction can only be used for fee estimation
///
/// - Returns: Signed invoke v3 transaction
func signV3(calls: [StarknetCall], params: StarknetInvokeParamsV3, forFeeEstimation: Bool) throws -> StarknetInvokeTransactionV3
func signV3(calls: [StarknetCall], params: StarknetInvokeParamsV3, forFeeEstimation: Bool) async throws -> StarknetInvokeTransactionV3

/// Create and sign deploy account transaction v1
///
Expand All @@ -34,7 +34,7 @@ public protocol StarknetAccountProtocol {
/// - forFeeEstimation: Flag indicating whether the different version of transaction should be used; such transaction can only be used for fee estimation
///
/// - Returns: Signed deploy account transaction v1
func signDeployAccountV1(classHash: Felt, calldata: StarknetCalldata, salt: Felt, params: StarknetDeployAccountParamsV1, forFeeEstimation: Bool) throws -> StarknetDeployAccountTransactionV1
func signDeployAccountV1(classHash: Felt, calldata: StarknetCalldata, salt: Felt, params: StarknetDeployAccountParamsV1, forFeeEstimation: Bool) async throws -> StarknetDeployAccountTransactionV1

/// Create and sign deploy account transaction v3
///
Expand All @@ -46,15 +46,15 @@ public protocol StarknetAccountProtocol {
/// - forFeeEstimation: Flag indicating whether the different version of transaction should be used; such transaction can only be used for fee estimation
///
/// - Returns: Signed deploy account transaction v3
func signDeployAccountV3(classHash: Felt, calldata: StarknetCalldata, salt: Felt, params: StarknetDeployAccountParamsV3, forFeeEstimation: Bool) throws -> StarknetDeployAccountTransactionV3
func signDeployAccountV3(classHash: Felt, calldata: StarknetCalldata, salt: Felt, params: StarknetDeployAccountParamsV3, forFeeEstimation: Bool) async throws -> StarknetDeployAccountTransactionV3

/// Sign TypedData for off-chain usage with this account's privateKey.
///
/// - Parameters:
/// - typedData: a TypedData object to sign
///
/// - Returns: a signature for provided TypedData object.
func sign(typedData: StarknetTypedData) throws -> StarknetSignature
func sign(typedData: StarknetTypedData) async throws -> StarknetSignature

/// Verify a signature of TypedData on Starknet.
///
Expand Down Expand Up @@ -158,8 +158,8 @@ public extension StarknetAccountProtocol {
/// - params: additional params for a given transaction
///
/// - Returns: Signed invoke transaction v1
func signV1(calls: [StarknetCall], params: StarknetInvokeParamsV1) throws -> StarknetInvokeTransactionV1 {
try signV1(calls: calls, params: params, forFeeEstimation: false)
func signV1(calls: [StarknetCall], params: StarknetInvokeParamsV1) async throws -> StarknetInvokeTransactionV1 {
try await signV1(calls: calls, params: params, forFeeEstimation: false)
}

/// Sign list of calls for execution as invoke transaction v3.
Expand All @@ -170,8 +170,8 @@ public extension StarknetAccountProtocol {
/// - params: additional params for a given transaction
///
/// - Returns: Signed invoke transaction v3
func signV3(calls: [StarknetCall], params: StarknetInvokeParamsV3) throws -> StarknetInvokeTransactionV3 {
try signV3(calls: calls, params: params, forFeeEstimation: false)
func signV3(calls: [StarknetCall], params: StarknetInvokeParamsV3) async throws -> StarknetInvokeTransactionV3 {
try await signV3(calls: calls, params: params, forFeeEstimation: false)
}

/// Create and sign deploy account transaction v1
Expand All @@ -184,8 +184,8 @@ public extension StarknetAccountProtocol {
/// - maxFee: max acceptable fee for the transaction
///
/// - Returns: Signed deploy account transaction v1
func signDeployAccountV1(classHash: Felt, calldata: StarknetCalldata, salt: Felt, maxFee: Felt) throws -> StarknetDeployAccountTransactionV1 {
try signDeployAccountV1(classHash: classHash, calldata: calldata, salt: salt, params: StarknetDeployAccountParamsV1(nonce: .zero, maxFee: maxFee), forFeeEstimation: false)
func signDeployAccountV1(classHash: Felt, calldata: StarknetCalldata, salt: Felt, maxFee: Felt) async throws -> StarknetDeployAccountTransactionV1 {
try await signDeployAccountV1(classHash: classHash, calldata: calldata, salt: salt, params: StarknetDeployAccountParamsV1(nonce: .zero, maxFee: maxFee), forFeeEstimation: false)
}

/// Create and sign deploy account transaction v3
Expand All @@ -198,8 +198,8 @@ public extension StarknetAccountProtocol {
/// - l1ResourceBounds: max acceptable l1 resource bounds
///
/// - Returns: Signed deploy account transaction v3
func signDeployAccountV3(classHash: Felt, calldata: StarknetCalldata, salt: Felt, l1ResourceBounds: StarknetResourceBounds) throws -> StarknetDeployAccountTransactionV3 {
try signDeployAccountV3(classHash: classHash, calldata: calldata, salt: salt, params: StarknetDeployAccountParamsV3(nonce: .zero, l1ResourceBounds: l1ResourceBounds), forFeeEstimation: false)
func signDeployAccountV3(classHash: Felt, calldata: StarknetCalldata, salt: Felt, l1ResourceBounds: StarknetResourceBounds) async throws -> StarknetDeployAccountTransactionV3 {
try await signDeployAccountV3(classHash: classHash, calldata: calldata, salt: salt, params: StarknetDeployAccountParamsV3(nonce: .zero, l1ResourceBounds: l1ResourceBounds), forFeeEstimation: false)
}

/// Sign a call as invoke transaction v1
Expand All @@ -210,8 +210,8 @@ public extension StarknetAccountProtocol {
/// - forFeeEstimation: Flag indicating whether the different version of transaction should be used; such transaction can only be used for fee estimation
///
/// - Returns: Signed invoke transaction v1
func signV1(call: StarknetCall, params: StarknetInvokeParamsV1, forFeeEstimation: Bool = false) throws -> StarknetInvokeTransactionV1 {
try signV1(calls: [call], params: params, forFeeEstimation: forFeeEstimation)
func signV1(call: StarknetCall, params: StarknetInvokeParamsV1, forFeeEstimation: Bool = false) async throws -> StarknetInvokeTransactionV1 {
try await signV1(calls: [call], params: params, forFeeEstimation: forFeeEstimation)
}

/// Sign a call as invoke transaction v3
Expand All @@ -221,8 +221,8 @@ public extension StarknetAccountProtocol {
/// - forFeeEstimation: Flag indicating whether the different version of transaction should be used; such transaction can only be used for fee estimation
///
/// - Returns: Signed invoke transaction v3
func signV3(call: StarknetCall, params: StarknetInvokeParamsV3, forFeeEstimation: Bool = false) throws -> StarknetInvokeTransactionV3 {
try signV3(calls: [call], params: params, forFeeEstimation: forFeeEstimation)
func signV3(call: StarknetCall, params: StarknetInvokeParamsV3, forFeeEstimation: Bool = false) async throws -> StarknetInvokeTransactionV3 {
try await signV3(calls: [call], params: params, forFeeEstimation: forFeeEstimation)
}

/// Execute list of calls as invoke transaction v1
Expand Down
22 changes: 13 additions & 9 deletions Sources/Starknet/Data/StarknetChainId.swift
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import BigInt
import Foundation

public enum StarknetChainId {
case mainnet
case testnet
public enum StarknetChainId: String, Codable, Equatable {
case mainnet = "0x534e5f4d41494e"
case goerli = "0x534e5f474f45524c49"
case sepolia = "0x534e5f5345504f4c4941"
case integration_sepolia = "0x534e5f494e544547524154494f4e5f5345504f4c4941"

public var feltValue: Felt {
switch self {
case .mainnet:
return Felt(fromHex: "0x534e5f4d41494e")!
case .testnet:
return Felt(fromHex: "0x534e5f474f45524c49")!
}
Felt(fromHex: self.rawValue)!
}

enum CodingKeys: String, CodingKey {
case mainnet = "0x534e5f4d41494e"
case goerli = "0x534e5f474f45524c49"
case sepolia = "0x534e5f5345504f4c4941"
case integration_sepolia = "0x534e5f494e544547524154494f4e5f5345504f4c4941"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ enum JsonRpcMethod: String, Encodable {
case getTransactionByHash = "starknet_getTransactionByHash"
case getTransactionByBlockIdAndIndex = "starknet_getTransactionByBlockIdAndIndex"
case getTransactionReceipt = "starknet_getTransactionReceipt"
case getTransactionStatus = "starknet_getTransactionStatus"
case getChainId = "starknet_chainId"
case simulateTransactions = "starknet_simulateTransactions"
case estimateMessageFee = "starknet_estimateMessageFee"
case getTransactionStatus = "starknet_getTransactionStatus"
}
24 changes: 14 additions & 10 deletions Sources/Starknet/Providers/StarknetProvider/StarknetProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,31 @@ public enum StarknetProviderError: Error {
}

public class StarknetProvider: StarknetProviderProtocol {
public let starknetChainId: StarknetChainId

private let url: URL
private let networkProvider: HttpNetworkProvider

public init(starknetChainId: StarknetChainId, url: URL) {
self.starknetChainId = starknetChainId
public init(url: URL) {
self.url = url
self.networkProvider = HttpNetworkProvider()
}

public convenience init?(starknetChainId: StarknetChainId, url: String) {
public convenience init?(url: String) {
guard let url = URL(string: url) else {
return nil
}
self.init(starknetChainId: starknetChainId, url: url)
self.init(url: url)
}

public init(starknetChainId: StarknetChainId, url: URL, urlSession: URLSession) {
self.starknetChainId = starknetChainId
public init(url: URL, urlSession: URLSession) {
self.url = url
self.networkProvider = HttpNetworkProvider(session: urlSession)
}

public convenience init?(starknetChainId: StarknetChainId, url: String, urlSession: URLSession) {
public convenience init?(url: String, urlSession: URLSession) {
guard let url = URL(string: url) else {
return nil
}
self.init(starknetChainId: starknetChainId, url: url, urlSession: urlSession)
self.init(url: url, urlSession: urlSession)
}

private func makeRequest<U>(method: JsonRpcMethod, params: some Encodable = EmptyParams(), receive _: U.Type) async throws -> U where U: Decodable {
Expand Down Expand Up @@ -182,6 +178,14 @@ public class StarknetProvider: StarknetProviderProtocol {
return result
}

public func getChainId() async throws -> StarknetChainId {
let params = EmptySequence()

let result = try await makeRequest(method: .getChainId, params: params, receive: StarknetChainId.self)

return result
}

public func simulateTransactions(_ transactions: [any StarknetExecutableTransaction], at blockId: StarknetBlockId, simulationFlags: Set<StarknetSimulationFlag>) async throws -> [StarknetSimulatedTransaction] {
let params = SimulateTransactionsParams(transactions: transactions, blockId: blockId, simulationFlags: simulationFlags)

Expand Down
Loading

0 comments on commit ad1cd44

Please sign in to comment.