diff --git a/js/package-lock.json b/js/package-lock.json index 90992221..29f4d969 100644 --- a/js/package-lock.json +++ b/js/package-lock.json @@ -24,7 +24,7 @@ "pg": "^8.14.1", "redlock": "^5.0.0-beta.2", "reflect-metadata": "^0.2.2", - "starknet": "^6.23.1", + "starknet": "^7.1.0", "tsyringe": "^4.9.1", "web3-provider-engine": "^17.0.1" }, @@ -9221,16 +9221,6 @@ "bser": "2.1.1" } }, - "node_modules/fetch-cookie": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-3.0.1.tgz", - "integrity": "sha512-ZGXe8Y5Z/1FWqQ9q/CrJhkUD73DyBU9VF0hBQmEO/wPHe4A9PKTjplFDLeFX8aOsYypZUcX5Ji/eByn3VCVO3Q==", - "license": "Unlicense", - "dependencies": { - "set-cookie-parser": "^2.4.8", - "tough-cookie": "^4.0.0" - } - }, "node_modules/fflate": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", @@ -10474,16 +10464,6 @@ "node": ">=16" } }, - "node_modules/isomorphic-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", - "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.6.1", - "whatwg-fetch": "^3.4.1" - } - }, "node_modules/isows": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", @@ -14949,12 +14929,6 @@ "randombytes": "^2.1.0" } }, - "node_modules/set-cookie-parser": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", - "license": "MIT" - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -15318,22 +15292,23 @@ "license": "MIT" }, "node_modules/starknet": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/starknet/-/starknet-6.24.1.tgz", - "integrity": "sha512-g7tiCt73berhcNi41otlN3T3kxZnIvZhMi8WdC21Y6GC6zoQgbI2z1t7JAZF9c4xZiomlanwVnurcpyfEdyMpg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/starknet/-/starknet-7.1.0.tgz", + "integrity": "sha512-7e5UCmRAng4hwYntNBYmsRo2ox+1ORh8GLO06uJnuW+SKPH6oBf+MSH+g/UntVb4tVUeQVeMrGLkLZ8h1Ghu2Q==", "license": "MIT", "dependencies": { "@noble/curves": "1.7.0", "@noble/hashes": "1.6.0", "@scure/base": "1.2.1", "@scure/starknet": "1.1.0", - "abi-wan-kanabi": "^2.2.3", - "fetch-cookie": "~3.0.0", - "isomorphic-fetch": "~3.0.0", + "abi-wan-kanabi": "2.2.4", + "isows": "^1.0.6", "lossless-json": "^4.0.1", "pako": "^2.0.4", - "starknet-types-07": "npm:@starknet-io/types-js@^0.7.10", - "ts-mixer": "^6.0.3" + "starknet-types-07": "npm:@starknet-io/types-js@~0.7.10", + "starknet-types-08": "npm:@starknet-io/types-js@~0.8.1", + "ts-mixer": "^6.0.3", + "ws": "^8.18.0" } }, "node_modules/starknet-types-07": { @@ -15343,6 +15318,13 @@ "integrity": "sha512-1VtCqX4AHWJlRRSYGSn+4X1mqolI1Tdq62IwzoU2vUuEE72S1OlEeGhpvd6XsdqXcfHmVzYfj8k1XtKBQqwo9w==", "license": "MIT" }, + "node_modules/starknet-types-08": { + "name": "@starknet-io/types-js", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/@starknet-io/types-js/-/types-js-0.8.4.tgz", + "integrity": "sha512-0RZ3TZHcLsUTQaq1JhDSCM8chnzO4/XNsSCozwDET64JK5bjFDIf2ZUkta+tl5Nlbf4usoU7uZiDI/Q57kt2SQ==", + "license": "MIT" + }, "node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -16118,21 +16100,6 @@ "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", "license": "MIT" }, - "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", - "license": "BSD-3-Clause", - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -17002,12 +16969,6 @@ "node": ">=10.13.0" } }, - "node_modules/whatwg-fetch": { - "version": "3.6.20", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", - "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", - "license": "MIT" - }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", diff --git a/js/package.json b/js/package.json index a6928726..7f472fac 100644 --- a/js/package.json +++ b/js/package.json @@ -26,7 +26,7 @@ "pg": "^8.14.1", "redlock": "^5.0.0-beta.2", "reflect-metadata": "^0.2.2", - "starknet": "^6.23.1", + "starknet": "^7.1.0", "tsyringe": "^4.9.1", "web3-provider-engine": "^17.0.1" }, diff --git a/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/FuelSignTransactionRequest.ts b/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/FuelSignTransactionRequestModel.ts similarity index 54% rename from js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/FuelSignTransactionRequest.ts rename to js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/FuelSignTransactionRequestModel.ts index cca3f062..2a8a5262 100644 --- a/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/FuelSignTransactionRequest.ts +++ b/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/FuelSignTransactionRequestModel.ts @@ -1,5 +1,5 @@ import { BaseSignTransactionRequestModel } from "./TreasurySignTransactionRequestModel"; -export interface FuelSignTransactionRequest extends BaseSignTransactionRequestModel { +export interface FuelSignTransactionRequestModel extends BaseSignTransactionRequestModel { nodeUrl: string; } \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/StarknetSignTransactionRequestModel.ts b/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/StarknetSignTransactionRequestModel.ts new file mode 100644 index 00000000..4142e086 --- /dev/null +++ b/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/StarknetSignTransactionRequestModel.ts @@ -0,0 +1,5 @@ +import { BaseSignTransactionRequestModel } from "./TreasurySignTransactionRequestModel"; + +export interface StarknetSignTransactionRequestModel extends BaseSignTransactionRequestModel { + signerInvocationDetails: string +} \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/index.ts b/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/index.ts index 067983e8..ff363b0d 100644 --- a/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/index.ts +++ b/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/index.ts @@ -1,13 +1,13 @@ import { TreasuryGenerateAddressResponseModel } from './TreasuryGenerateAddressResponseModel'; import { TreasurySignTransactionResponseModel } from './TreasurySignTransactionResponseModel'; import { BaseSignTransactionRequestModel } from './TreasurySignTransactionRequestModel'; -import { FuelSignTransactionRequest } from './FuelSignTransactionRequest'; -import { AztecSignTransactionRequest } from './AztecSignTransactionRequest'; +import { FuelSignTransactionRequestModel } from './FuelSignTransactionRequestModel'; +import { StarknetSignTransactionRequestModel } from './StarknetSignTransactionRequestModel'; export { TreasuryGenerateAddressResponseModel, TreasurySignTransactionResponseModel, BaseSignTransactionRequestModel, - FuelSignTransactionRequest, - AztecSignTransactionRequest, + FuelSignTransactionRequestModel, + StarknetSignTransactionRequestModel }; \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/treasuryClient.ts b/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/treasuryClient.ts index cc2d81b4..86c59c09 100644 --- a/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/treasuryClient.ts +++ b/js/src/Blockchain/Blockchain.Abstraction/Infrastructure/TreasuryClient/treasuryClient.ts @@ -2,13 +2,14 @@ import { BaseSignTransactionRequestModel, TreasuryGenerateAddressResponseModel, TreasurySignTransactionResponseModel, - FuelSignTransactionRequest, - AztecSignTransactionRequest, + FuelSignTransactionRequestModel, + StarknetSignTransactionRequestModel, } from "./Models"; import axios from "axios"; +import { AztecSignTransactionRequest } from "./Models/AztecSignTransactionRequest"; export class TreasuryClient { - private apiClient + private apiClient; constructor(signerAgentUrl: string) { this.apiClient = axios.create({ @@ -20,7 +21,7 @@ export class TreasuryClient { async signTransaction( networkType: string, - request: BaseSignTransactionRequestModel | FuelSignTransactionRequest | AztecSignTransactionRequest + request: BaseSignTransactionRequestModel | FuelSignTransactionRequestModel | StarknetSignTransactionRequestModel | AztecSignTransactionRequest ): Promise { const res = await this.apiClient.post( `${networkType.toLowerCase()}/sign`, diff --git a/js/src/Blockchain/Blockchain.Abstraction/Models/AllowanceRequest.ts b/js/src/Blockchain/Blockchain.Abstraction/Models/AllowanceRequest.ts index 107cd1be..244bb479 100644 --- a/js/src/Blockchain/Blockchain.Abstraction/Models/AllowanceRequest.ts +++ b/js/src/Blockchain/Blockchain.Abstraction/Models/AllowanceRequest.ts @@ -2,6 +2,5 @@ import { BaseRequest } from "./BaseRequest"; export interface AllowanceRequest extends BaseRequest { ownerAddress: string; - spenderAddress: string; asset: string; } \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Abstraction/Models/FeesModels/EstimateFeeRequest.ts b/js/src/Blockchain/Blockchain.Abstraction/Models/FeesModels/EstimateFeeRequest.ts index 3c3d3252..6f6e32ac 100644 --- a/js/src/Blockchain/Blockchain.Abstraction/Models/FeesModels/EstimateFeeRequest.ts +++ b/js/src/Blockchain/Blockchain.Abstraction/Models/FeesModels/EstimateFeeRequest.ts @@ -6,4 +6,5 @@ export interface EstimateFeeRequest extends BaseRequest { fromAddress: string, asset: string, callData?: string + nonce: string } \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Abstraction/Models/WalletsModels/HookedWalletEthTxSubprovider.ts b/js/src/Blockchain/Blockchain.Abstraction/Models/WalletsModels/HookedWalletEthTxSubprovider.ts deleted file mode 100644 index beeb9e73..00000000 --- a/js/src/Blockchain/Blockchain.Abstraction/Models/WalletsModels/HookedWalletEthTxSubprovider.ts +++ /dev/null @@ -1,50 +0,0 @@ -// From https://github.com/trufflesuite/truffle/blob/v5.7.2/packages/hdwallet-provider/src/index.ts - -const HookedWalletProvider = require('web3-provider-engine/subproviders/hooked-wallet'); -import { signTypedData, SignTypedDataVersion, personalSign } from "@metamask/eth-sig-util"; - -export class HookedWalletTypedSignatureSubprovider extends HookedWalletProvider { - - constructor(private _opts: any) { - super(_opts) - } - - // https://github.com/trufflesuite/truffle/blob/v5.7.2/packages/hdwallet-provider/src/index.ts#L228 - signTypedMessage({ data, from }: { data: string; from: string }, cb: any) { - this._opts.getPrivateKey(from, function (err: any, privateKey: any) { - if (err) return cb(err) - - if (!data) { - cb("No data to sign"); - return; - } - - const signature = signTypedData({ - data: JSON.parse(data), - privateKey: privateKey, - version: SignTypedDataVersion.V4 - }); - - cb(null, signature); - }) - } - - signMessage({ data, from }: any, cb: any) { - this._opts.getPrivateKey(from, function (err: any, privateKey: any) { - if (err) return cb(err) - - if (!data) { - cb("No data to sign"); - return; - } - - const signature = personalSign({ privateKey, data }) - - cb(null, signature); - }) - } - - signPersonalMessage(payload: any, cb: any) { - this.signMessage(payload, cb); - }; -} diff --git a/js/src/Blockchain/Blockchain.Abstraction/Models/WalletsModels/PrivateKeyProvider.ts b/js/src/Blockchain/Blockchain.Abstraction/Models/WalletsModels/PrivateKeyProvider.ts deleted file mode 100644 index 5609af6f..00000000 --- a/js/src/Blockchain/Blockchain.Abstraction/Models/WalletsModels/PrivateKeyProvider.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { HookedWalletTypedSignatureSubprovider } from "./HookedWalletEthTxSubprovider"; -import RpcSubprovider from 'web3-provider-engine/subproviders/rpc'; -import Web3ProviderEngine from 'web3-provider-engine'; -import { Wallet } from 'ethers' - -function PrivateKeyProvider(privateKey: string, providerUrl: string = null) { - if (!privateKey) { - throw new Error(`Private Key missing, non-empty string expected, got "${privateKey}"`); - } - - this._providers = [] - - let wallet = new Wallet(privateKey); - var walletProvider = new HookedWalletTypedSignatureSubprovider({ - getAccounts: function (cb) { - cb(null, [wallet.address]) - }, - getPrivateKey: function (address, cb) { - if (address.toLowerCase() !== wallet.address.toLowerCase()) { - return cb('Account not found') - } - - let privateKey = wallet.privateKey; - if (privateKey.startsWith("0x")) { - privateKey = privateKey.substring(2); - } - - cb(null, privateKey) - } - }); - - this._providers.push(walletProvider); - if (providerUrl) { - this._providers.push(new RpcSubprovider({ rpcUrl: providerUrl })); - } -} - -PrivateKeyProvider.prototype._handleAsync = Web3ProviderEngine.prototype._handleAsync; - -PrivateKeyProvider.prototype.sendAsync = function (payload, cb) { - this._handleAsync(payload, cb) -} - -export default PrivateKeyProvider; diff --git a/js/src/Blockchain/Blockchain.Abstraction/Models/WalletsModels/PrivateKeyRepository.ts b/js/src/Blockchain/Blockchain.Abstraction/Models/WalletsModels/PrivateKeyRepository.ts deleted file mode 100644 index 9b78961d..00000000 --- a/js/src/Blockchain/Blockchain.Abstraction/Models/WalletsModels/PrivateKeyRepository.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { promises as fs } from 'fs'; -import nodeVault, { client } from 'node-vault' - -export class PrivateKeyRepository { - private pkKey: string = 'private_key'; - private vault: client; - private getTokenAsync!: () => Promise; - - constructor() { - this.vault = nodeVault({ - endpoint: process.env.TrainSolver__HashicorpKeyVaultUri - }); - - this.initLogin(); - } - - public async getAsync(address: string): Promise { - await this.getTokenAsync(); - const keyVaultMount = process.env.TrainSolver__HashicorpKeyVaultMountPath ?? 'secret'; - const {data} = await this.vault.read(`${keyVaultMount}/data/${address}`); - return data.data[this.pkKey]; - } - - public async getStarkPKAsync(address: string, network: string): Promise { - var key = `STARK-${network.replace('_', '-')}--${address.toLowerCase()}`; - return this.getAsync(key); - } - - private initLogin(): void { - const useKubernetesAuth = process.env.TrainSolver__HashicorpEnableKubernetesAuth === 'true'; - - this.getTokenAsync = useKubernetesAuth - ? async () => { - const k8sJWTPath = process.env.K8S_SERVICE_ACCOUNT_TOKEN_PATH; - var k8sRole = process.env.TrainSolver__HashicorpKeyVaultK8sAppRole; - const k8sJWT = await fs.readFile(k8sJWTPath, 'utf8'); - - await this.vault.kubernetesLogin({role: k8sRole , jwt: k8sJWT, mount_point: "kubernetes"}); - } - : async () => { - const userName = process.env.TrainSolver__HashicorpKeyVaultUsername; - const password = process.env.TrainSolver__HashicorpKeyVaultPassword; - - await this.vault - .userpassLogin({ - username: userName, - password: password, - mount_point: 'userpass', - }) - }; - } -} \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Aztec/Activities/Models/AztecSignTransactionModel.ts b/js/src/Blockchain/Blockchain.Aztec/Activities/Models/AztecSignTransactionModel.ts index f4fe712f..cea8a529 100644 --- a/js/src/Blockchain/Blockchain.Aztec/Activities/Models/AztecSignTransactionModel.ts +++ b/js/src/Blockchain/Blockchain.Aztec/Activities/Models/AztecSignTransactionModel.ts @@ -1,4 +1,4 @@ -import { AztecSignTransactionRequest } from "../../../Blockchain.Abstraction/Infrastructure/TreasuryClient/Models"; +import { AztecSignTransactionRequest } from "../../../Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/AztecSignTransactionRequest"; export interface AztecSignTransactionRequestModel { networkType: string; diff --git a/js/src/Blockchain/Blockchain.Fuel/Activities/FuelBlockchainActivities.ts b/js/src/Blockchain/Blockchain.Fuel/Activities/FuelBlockchainActivities.ts index 11aebf9d..c511cd63 100644 --- a/js/src/Blockchain/Blockchain.Fuel/Activities/FuelBlockchainActivities.ts +++ b/js/src/Blockchain/Blockchain.Fuel/Activities/FuelBlockchainActivities.ts @@ -24,7 +24,7 @@ import { inject, injectable } from "tsyringe"; import Redis from "ioredis"; import Redlock from "redlock"; import { TreasuryClient } from "../../Blockchain.Abstraction/Infrastructure/TreasuryClient/treasuryClient"; -import { FuelSignTransactionRequestModel } from "./Models/FuelSignTransactionModel"; +import { SignTransactionRequest } from "./Models/FuelSignTransactionModel"; import { TransactionFailedException } from "../../Blockchain.Abstraction/Exceptions/TransactionFailedException"; import { CurrentNonceRequest } from "../../Blockchain.Abstraction/Models/NonceModels/CurrentNonceRequest"; import { NextNonceRequest } from "../../Blockchain.Abstraction/Models/NonceModels/NextNonceRequest"; @@ -294,7 +294,7 @@ export class FuelBlockchainActivities implements IFuelBlockchainActivities { } } - public async SignTransaction(request: FuelSignTransactionRequestModel): Promise { + public async SignTransaction(request: SignTransactionRequest): Promise { const treasuryClient = new TreasuryClient(request.signerAgentUrl); diff --git a/js/src/Blockchain/Blockchain.Fuel/Activities/Helper/FuelEventTracker.ts b/js/src/Blockchain/Blockchain.Fuel/Activities/Helper/FuelEventTracker.ts index 0edde747..1d46a1a0 100644 --- a/js/src/Blockchain/Blockchain.Fuel/Activities/Helper/FuelEventTracker.ts +++ b/js/src/Blockchain/Blockchain.Fuel/Activities/Helper/FuelEventTracker.ts @@ -2,11 +2,9 @@ import { bn, Contract, DateTime, Provider, ReceiptType } from "fuels"; import abi from '../ABIs/train.json'; import { HTLCBlockEventResponse, HTLCCommitEventMessage, HTLCLockEventMessage } from "../../../Blockchain.Abstraction/Models/EventModels/HTLCBlockEventResposne"; -import { TokenCommittedEvent } from "../Models/FuelTokenCommitedEvents"; -import { TokenLockedEvent } from "../Models/FuelTokenLockedEvent"; import { DetailedNetworkDto } from "../../../Blockchain.Abstraction/Models/DetailedNetworkDto"; import { FormatAddress } from "../FuelBlockchainActivities"; -import { ethers } from "ethers"; +import { TokenCommittedEvent, TokenLockedEvent } from "../Models/EventModels"; export default async function TrackBlockEventsAsync( network: DetailedNetworkDto, diff --git a/js/src/Blockchain/Blockchain.Fuel/Activities/IFuelBlockchainActivities.ts b/js/src/Blockchain/Blockchain.Fuel/Activities/IFuelBlockchainActivities.ts index 26950591..1c5c0f59 100644 --- a/js/src/Blockchain/Blockchain.Fuel/Activities/IFuelBlockchainActivities.ts +++ b/js/src/Blockchain/Blockchain.Fuel/Activities/IFuelBlockchainActivities.ts @@ -3,7 +3,7 @@ import { GetTransactionRequest } from "../../Blockchain.Abstraction/Models/Recei import { TransactionResponse } from "../../Blockchain.Abstraction/Models/ReceiptModels/TransactionResponse"; import { FuelPublishTransactionRequest } from "../Models/FuelPublishTransactionRequest"; import { FuelComposeTransactionRequest } from "../Models/FuelComposeTransactionRequest"; -import { FuelSignTransactionRequestModel } from "./Models/FuelSignTransactionModel"; +import { SignTransactionRequest } from "./Models/FuelSignTransactionModel"; import { NextNonceRequest } from "../../Blockchain.Abstraction/Models/NonceModels/NextNonceRequest"; import { CurrentNonceRequest } from "../../Blockchain.Abstraction/Models/NonceModels/CurrentNonceRequest"; @@ -15,7 +15,7 @@ export interface IFuelBlockchainActivities extends IBlockchainActivities { ComposeRawTransaction(request: FuelComposeTransactionRequest): Promise; - SignTransaction(request: FuelSignTransactionRequestModel): Promise; + SignTransaction(request: SignTransactionRequest): Promise; GetNextNonce(request: NextNonceRequest): Promise; diff --git a/js/src/Blockchain/Blockchain.Fuel/Activities/Models/EventModels.ts b/js/src/Blockchain/Blockchain.Fuel/Activities/Models/EventModels.ts new file mode 100644 index 00000000..458f6c14 --- /dev/null +++ b/js/src/Blockchain/Blockchain.Fuel/Activities/Models/EventModels.ts @@ -0,0 +1,22 @@ +export interface TokenCommittedEvent { + Id: string; + dstChain: string; + dstAddress: string; + dstAsset: string; + srcAsset: string; + amount: string; + timelock: string; + srcReceiver: AddressBits; + sender: AddressBits; + assetId: AddressBits; +} + +interface AddressBits { + bits: string; +} + +export interface TokenLockedEvent { + hashlock: string; + timelock: string; + Id: string; +} \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Fuel/Activities/Models/FuelSignTransactionModel.ts b/js/src/Blockchain/Blockchain.Fuel/Activities/Models/FuelSignTransactionModel.ts index 52f5cd82..de08be64 100644 --- a/js/src/Blockchain/Blockchain.Fuel/Activities/Models/FuelSignTransactionModel.ts +++ b/js/src/Blockchain/Blockchain.Fuel/Activities/Models/FuelSignTransactionModel.ts @@ -1,7 +1,7 @@ -import { FuelSignTransactionRequest } from "../../../Blockchain.Abstraction/Infrastructure/TreasuryClient/Models"; +import { FuelSignTransactionRequestModel } from "../../../Blockchain.Abstraction/Infrastructure/TreasuryClient/Models"; -export interface FuelSignTransactionRequestModel { +export interface SignTransactionRequest { networkType: string; - signRequest: FuelSignTransactionRequest; + signRequest: FuelSignTransactionRequestModel; signerAgentUrl: string; } \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Fuel/Activities/Models/FuelTokenCommitedEvents.ts b/js/src/Blockchain/Blockchain.Fuel/Activities/Models/FuelTokenCommitedEvents.ts deleted file mode 100644 index 4f0315f5..00000000 --- a/js/src/Blockchain/Blockchain.Fuel/Activities/Models/FuelTokenCommitedEvents.ts +++ /dev/null @@ -1,16 +0,0 @@ -export interface TokenCommittedEvent { - Id: string; - dstChain: string; - dstAddress: string; - dstAsset: string; - srcAsset: string; - amount: string; - timelock: string; - srcReceiver: AddressBits; - sender: AddressBits; - assetId: AddressBits; -} - -interface AddressBits { - bits: string; -} diff --git a/js/src/Blockchain/Blockchain.Fuel/Activities/Models/FuelTokenLockedEvent.ts b/js/src/Blockchain/Blockchain.Fuel/Activities/Models/FuelTokenLockedEvent.ts deleted file mode 100644 index 597a3ee7..00000000 --- a/js/src/Blockchain/Blockchain.Fuel/Activities/Models/FuelTokenLockedEvent.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface TokenLockedEvent { - hashlock: string; - timelock: string; - Id: string; - } - \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Fuel/Workflows/FuelTransactionProcessor.ts b/js/src/Blockchain/Blockchain.Fuel/Workflows/FuelTransactionProcessor.ts index ae418182..ecb8fcb3 100644 --- a/js/src/Blockchain/Blockchain.Fuel/Workflows/FuelTransactionProcessor.ts +++ b/js/src/Blockchain/Blockchain.Fuel/Workflows/FuelTransactionProcessor.ts @@ -65,17 +65,15 @@ export async function FuelTransactionProcessor( callDataAmount: Number(preparedTransaction.callDataAmount), }); - const signedRawData = await defaultActivities.SignTransaction( - { - signerAgentUrl: request.signerAgentUrl, - networkType: NetworkType[request.network.type], - signRequest: { - unsignedTxn: rawTx, - address: request.fromAddress, - nodeUrl: request.network.nodes[0].url, - } + const signedRawData = await defaultActivities.SignTransaction({ + signerAgentUrl: request.signerAgentUrl, + networkType: NetworkType[request.network.type], + signRequest: { + unsignedTxn: rawTx, + address: request.fromAddress, + nodeUrl: request.network.nodes[0].url, } - ); + }); const publishedTransaction = await nonRetryableActivities.PublishTransaction({ network: request.network, @@ -88,15 +86,13 @@ export async function FuelTransactionProcessor( }); transactionResponse.asset = preparedTransaction.callDataAsset; - transactionResponse.amount = preparedTransaction.callDataAmount.toString(); + transactionResponse.amount = preparedTransaction.callDataAmount; - await defaultActivities.UpdateCurrentNonce( - { - address: request.fromAddress, - network: request.network, - currentNonce: nextNonce - } - ) + await defaultActivities.UpdateCurrentNonce({ + address: request.fromAddress, + network: request.network, + currentNonce: nextNonce + }); return transactionResponse; @@ -108,8 +104,7 @@ export async function FuelTransactionProcessor( address: request.fromAddress, network: request.network, currentNonce: nextNonce - } - ) + }); if ((error instanceof ApplicationFailure && error.type === 'TransactionFailedException')) { diff --git a/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/Client.ts b/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/Client.ts new file mode 100644 index 00000000..0845f7fa --- /dev/null +++ b/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/Client.ts @@ -0,0 +1,25 @@ +export async function sendInvocation(rpcUrl: string, invocation: object): Promise { + + const res = await fetch( + rpcUrl, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: 1, + method: "starknet_addInvokeTransaction", + params: [invocation], + }), + }); + + const body = await res.json(); + + if (body.error) { + throw new Error(`RPC error ${body.error.code}: ${body.error.message}`); + } + + if (body.result.transaction_hash) { + return body.result.transaction_hash; + } +} diff --git a/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/ErrorParser.ts b/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/ErrorParser.ts index f33cbbc9..6e9c3ef1 100644 --- a/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/ErrorParser.ts +++ b/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/ErrorParser.ts @@ -1,8 +1,8 @@ export function ParseNonces(errorMessage: string): { expectedNonce: BigInt; providedNonce: BigInt; -} | null { - +} { + if (!errorMessage) { return null; } diff --git a/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/StarknetEventTracker.ts b/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/StarknetEventTracker.ts index 5a1fb160..3092a789 100644 --- a/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/StarknetEventTracker.ts +++ b/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/StarknetEventTracker.ts @@ -1,13 +1,11 @@ import { CallData, hash, num, Provider } from "starknet"; -import { TokenLockedEvent as TokenLockAddedEvent, TokenLockedEvent } from "../../Models/StarknetTokenLockedEvent"; import { events } from 'starknet'; import trainAbi from '../ABIs/Train.json'; -import { TokenCommittedEvent as TokenCommittedEvent } from "../../Models/StarknetTokenCommittedEvent"; import { formatAddress} from "../StarknetBlockchainActivities"; -import { formatUnits } from "ethers/lib/utils"; import { HTLCBlockEventResponse, HTLCCommitEventMessage, HTLCLockEventMessage } from "../../../Blockchain.Abstraction/Models/EventModels/HTLCBlockEventResposne"; import { BigIntToAscii, toHex } from "../../../Blockchain.Abstraction/Extensions/StringExtensions"; import { DetailedNetworkDto } from "../../../Blockchain.Abstraction/Models/DetailedNetworkDto"; +import { TokenCommittedEvent, TokenLockedEvent } from "../../Models/EventModels"; export async function TrackBlockEventsAsync( @@ -76,7 +74,7 @@ export async function TrackBlockEventsAsync( response.htlcCommitEventMessages.push(commitMsg); } else if (eventName.endsWith("TokenLockAdded")) { - const data = eventData as unknown as TokenLockAddedEvent; + const data = eventData as unknown as TokenLockedEvent; const lockMsg: HTLCLockEventMessage = { txId: parsed.transaction_hash, @@ -94,4 +92,4 @@ export async function TrackBlockEventsAsync( export type ContractEvent = | Partial<{ TokenCommitted: TokenCommittedEvent }> - | Partial<{ TokenLockAdded: TokenLockAddedEvent }>; \ No newline at end of file + | Partial<{ TokenLockAdded: TokenLockedEvent }>; \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/StarknetTransactionBuilder.ts b/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/StarknetTransactionBuilder.ts index 0b9d1774..1de78cc6 100644 --- a/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/StarknetTransactionBuilder.ts +++ b/js/src/Blockchain/Blockchain.Starknet/Activities/Helper/StarknetTransactionBuilder.ts @@ -1,5 +1,5 @@ import { utils } from "ethers"; -import { cairo, Call, shortString, byteArray } from "starknet"; +import { cairo, Call, shortString, byteArray, Invocation } from "starknet"; import { decodeJson } from "../../../Blockchain.Abstraction/Extensions/StringExtensions"; import { ApprovePrepareRequest } from "../../../Blockchain.Abstraction/Models/TransactionBuilderModels/ApprovePrepareRequest"; import { HTLCAddLockSigTransactionPrepareRequest } from "../../../Blockchain.Abstraction/Models/TransactionBuilderModels/HTLCAddLockSigTransactionPrepareRequest"; @@ -27,7 +27,7 @@ export function createRefundCallData(network: DetailedNetworkDto, args: string): const callData = [cairo.uint256(refundRequest.commitId)]; - const methodCall: Call = { + const methodCall: Invocation = { contractAddress: htlcContractAddress, entrypoint: "refund", calldata: callData @@ -62,7 +62,7 @@ export function createRedeemCallData(network: DetailedNetworkDto, args: string): cairo.uint256(redeemRequest.secret) ]; - const methodCall: Call = { + const methodCall: Invocation = { contractAddress: htlcContractAddress, entrypoint: "redeem", calldata: callData @@ -107,7 +107,7 @@ export function createLockCallData(network: DetailedNetworkDto, args: string): P token.contract ]; - const methodCall: Call = { + const methodCall: Invocation = { contractAddress: htlcContractAddress, entrypoint: "lock", calldata: callData @@ -145,7 +145,7 @@ export function createAddLockSigCallData(network: DetailedNetworkDto, args: stri cairo.uint256(addLockSigRequest.timelock), addLockSigRequest.signatureArray ]; - const methodCall: Call = { + const methodCall: Invocation = { contractAddress: htlcContractAddress, entrypoint: "addLockSig", calldata: callData @@ -180,7 +180,7 @@ export function createApproveCallData(network: DetailedNetworkDto, args: string) cairo.uint256(Number(utils.parseUnits(approveRequest.amount.toString(), token.decimals))) ]; - const methodCall: Call = { + const methodCall: Invocation = { contractAddress: token.contract, entrypoint: "approve", calldata: callData @@ -210,7 +210,7 @@ export function createTransferCallData(network: DetailedNetworkDto, args: string cairo.uint256(Number(utils.parseUnits(transferRequest.amount.toString(), token.decimals))) ]; - const methodCall: Call = { + const methodCall: Invocation = { contractAddress: token.contract, entrypoint: "transfer", calldata: callData diff --git a/js/src/Blockchain/Blockchain.Starknet/Activities/IStarknetBlockchainActivities.ts b/js/src/Blockchain/Blockchain.Starknet/Activities/IStarknetBlockchainActivities.ts index e172a4f5..7b55d754 100644 --- a/js/src/Blockchain/Blockchain.Starknet/Activities/IStarknetBlockchainActivities.ts +++ b/js/src/Blockchain/Blockchain.Starknet/Activities/IStarknetBlockchainActivities.ts @@ -10,24 +10,33 @@ import { TransactionResponse } from "../../Blockchain.Abstraction/Models/Receipt import { AddLockSignatureRequest } from "../../Blockchain.Abstraction/Models/TransactionBuilderModels/AddLockSignatureRequest"; import { TransactionBuilderRequest } from "../../Blockchain.Abstraction/Models/TransactionBuilderModels/TransactionBuilderRequest"; import { PrepareTransactionResponse } from "../../Blockchain.Abstraction/Models/TransactionBuilderModels/TransferBuilderResponse"; -import { StarknetPublishTransactionRequest } from "../Models/StarknetPublishTransactionRequest "; +import { ComposeRawTransactionRequest, ComposeRawTransactionResponse } from "../Models/ComposeRawTxModels"; +import { EnsureSufficientBalanceRequest } from "../Models/EnsureSufficientBalanceModels"; +import { PublishTransactionRequest, SimulateTransactionRequest } from "../Models/TransactionModels"; +import { SignTransactionRequest } from "../Models/SignTransactionRequest"; export interface IStarknetBlockchainActivities extends IBlockchainActivities { - SimulateTransaction(request: StarknetPublishTransactionRequest): Promise; + SimulateTransaction(request: SimulateTransactionRequest): Promise; GetSpenderAllowance(request: AllowanceRequest): Promise; - PublishTransaction(request: StarknetPublishTransactionRequest): Promise; + PublishTransaction(request: PublishTransactionRequest): Promise; GetBatchTransaction(request: GetBatchTransactionRequest): Promise; EstimateFee(request: EstimateFeeRequest): Promise; - getNextNonce(request: NextNonceRequest): Promise; + GetNextNonce(request: NextNonceRequest): Promise; BuildTransaction(request: TransactionBuilderRequest): Promise; GetTransaction(request: GetTransactionRequest): Promise; - ValidateAddLockSignature(request: AddLockSignatureRequest): Promise + ValidateAddLockSignature(request: AddLockSignatureRequest): Promise; + + EnsureSufficientBalance(request: EnsureSufficientBalanceRequest): Promise; + + ComposeRawTransaction(request: ComposeRawTransactionRequest): Promise; + + SignTransaction(request: SignTransactionRequest): Promise; } \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Starknet/Activities/StarknetBlockchainActivities.ts b/js/src/Blockchain/Blockchain.Starknet/Activities/StarknetBlockchainActivities.ts index a8cdb98d..5c71b5c7 100644 --- a/js/src/Blockchain/Blockchain.Starknet/Activities/StarknetBlockchainActivities.ts +++ b/js/src/Blockchain/Blockchain.Starknet/Activities/StarknetBlockchainActivities.ts @@ -1,13 +1,11 @@ -import { Abi, Account, cairo, Call, constants, Contract, hash, RpcProvider, shortString, transaction, TransactionType as StarknetTransactionType, uint256, addAddressPadding } from "starknet"; -import { ETransactionVersion2, TypedData, TypedDataRevision } from "starknet-types-07"; +import { Abi, cairo, Call, Contract, hash, RpcProvider, shortString, uint256, addAddressPadding, Invocation, SuccessfulTransactionReceiptResponse, InvocationsSignerDetails, stark, AccountInvocations, TransactionType as StarknetTransactionType, v3hash } from "starknet"; +import { TypedData, TypedDataRevision } from "starknet-types-07"; import { injectable, inject } from "tsyringe"; import erc20Json from './ABIs/ERC20.json' -import { StarknetPublishTransactionRequest } from "../Models/StarknetPublishTransactionRequest "; +import { PublishTransactionRequest, SimulateTransactionRequest } from "../Models/TransactionModels"; import { BigNumber, utils } from "ethers"; import { InvalidTimelockException } from "../../Blockchain.Abstraction/Exceptions/InvalidTimelockException"; -import { PrivateKeyRepository } from "../../Blockchain.Abstraction/Models/WalletsModels/PrivateKeyRepository"; import { ParseNonces } from "./Helper/ErrorParser"; -import { CalcV2InvokeTxHashArgs } from "../Models/StarknetTransactioCalculationType"; import { TransactionFailedException } from "../../Blockchain.Abstraction/Exceptions/TransactionFailedException"; import { TrackBlockEventsAsync } from "./Helper/StarknetEventTracker"; import Redis from "ioredis"; @@ -37,6 +35,10 @@ import { TransactionType } from "../../Blockchain.Abstraction/Models/Transaciton import { TransactionBuilderRequest } from "../../Blockchain.Abstraction/Models/TransactionBuilderModels/TransactionBuilderRequest"; import { TransactionNotComfirmedException } from "../../Blockchain.Abstraction/Exceptions/TransactionNotComfirmedException"; import { DetailedNetworkDto } from "../../Blockchain.Abstraction/Models/DetailedNetworkDto"; +import { EnsureSufficientBalanceRequest } from "../Models/EnsureSufficientBalanceModels"; +import { ComposeRawTransactionRequest, ComposeRawTransactionResponse } from "../Models/ComposeRawTxModels"; +import { SignTransactionRequest } from "../Models/SignTransactionRequest"; +import { sendInvocation } from "./Helper/Client"; import { TreasuryClient } from "../../Blockchain.Abstraction/Infrastructure/TreasuryClient/treasuryClient"; @injectable() @@ -44,33 +46,83 @@ export class StarknetBlockchainActivities implements IStarknetBlockchainActiviti constructor( @inject("Redis") private redis: Redis, @inject("Redlock") private lockFactory: Redlock, - @inject("TreasuryClient") private treasuryClient: TreasuryClient ) { } - readonly FeeSymbol = "ETH"; - readonly FeeDecimals = 18; readonly FEE_ESTIMATE_MULTIPLIER = BigInt(4); - public async GetBatchTransaction(request: GetBatchTransactionRequest): Promise { - let transaction: TransactionResponse = null; + public async BuildTransaction(request: TransactionBuilderRequest): Promise { + try { + switch (request.type) { + case TransactionType.HTLCLock: + return createLockCallData(request.network, request.prepareArgs); + case TransactionType.HTLCRedeem: + return createRedeemCallData(request.network, request.prepareArgs); + case TransactionType.HTLCRefund: + return createRefundCallData(request.network, request.prepareArgs); + case TransactionType.HTLCAddLockSig: + return createAddLockSigCallData(request.network, request.prepareArgs); + case TransactionType.Approve: + return createApproveCallData(request.network, request.prepareArgs); + case TransactionType.Transfer: + return createTransferCallData(request.network, request.prepareArgs); + case TransactionType.HTLCCommit: + return createCommitCallData(request.network, request.prepareArgs); + default: + throw new Error(`Unknown function name ${request.type}`); + } + } + catch (error) { + throw error; + } + } - for (const transactionId of request.TransactionHashes) { - transaction = await this.GetTransactionByHashAsync(request.network, transactionId); + public async GetBalance(request: BalanceRequest): Promise { + try { + const token = request.network.tokens.find(t => t.symbol === request.asset); + + if (!token) { + throw new Error(`Token not found for network ${request.network.name} and asset ${request.asset}`); + } + + const provider = new RpcProvider({ + nodeUrl: request.network.nodes[0].url + }); + + const erc20 = new Contract(erc20Json as Abi, token.contract, provider); + const balanceResult = await erc20.balanceOf(request.address); + const balanceInWei = BigNumber.from(uint256.uint256ToBN(balanceResult.balance as any).toString()); + + let result: BalanceResponse = { + amount: Number(balanceInWei) + } + + return result; + } + catch (error) { + throw error; } + } + + public async GetTransaction(request: GetTransactionRequest): Promise { + + const transaction = await this.GetTransactionByHashAsync(request.network, request.transactionHash); if (!transaction) { - throw new TransactionNotComfirmedException("Transaction not confirmed"); + throw new TransactionNotComfirmedException(`Transaction ${request.transactionHash} not found`); } return transaction; } - public async GetTransaction(request: GetTransactionRequest): Promise { + public async GetBatchTransaction(request: GetBatchTransactionRequest): Promise { + let transaction: TransactionResponse = null; - const transaction = await this.GetTransactionByHashAsync(request.network, request.transactionHash); + for (const transactionId of request.TransactionHashes) { + transaction = await this.GetTransactionByHashAsync(request.network, transactionId); + } if (!transaction) { - throw new TransactionNotComfirmedException(`Transaction ${request.transactionHash} not found`); + throw new TransactionNotComfirmedException("Transaction not confirmed"); } return transaction; @@ -92,15 +144,15 @@ export class StarknetBlockchainActivities implements IStarknetBlockchainActiviti const transactionReceiptResponse = await provider.getTransactionReceipt(transactionHash); - const confrimedTransaction = transactionReceiptResponse.isSuccess() ? transactionReceiptResponse : null; + const confrimedTransaction = transactionReceiptResponse.value as SuccessfulTransactionReceiptResponse if (!confrimedTransaction) { return null; } - const feeInWei = confrimedTransaction.actual_fee.amount; + const blockData = await provider.getBlockWithTxHashes(confrimedTransaction.block_number); - const feeAmount = Number(utils.formatUnits(BigNumber.from(feeInWei), this.FeeDecimals)); + const feeAmount = confrimedTransaction.actual_fee; let transactionModel: TransactionResponse = { transactionHash: transactionHash, @@ -110,19 +162,10 @@ export class StarknetBlockchainActivities implements IStarknetBlockchainActiviti status: transactionStatus, feeAsset: network.nativeToken.symbol, feeAmount: feeAmount.toString(), - timestamp: new Date(), - networkName: network.name, + timestamp: new Date(blockData.timestamp * 1000), + networkName: network.name }; - const isConfirmed = "block_number" in confrimedTransaction; - - if (isConfirmed) { - const blockNumber = confrimedTransaction.block_number as string; - const blockData = await provider.getBlockWithTxHashes(blockNumber); - - transactionModel.timestamp = new Date(blockData.timestamp * 1000); - } - return transactionModel; } @@ -163,7 +206,7 @@ export class StarknetBlockchainActivities implements IStarknetBlockchainActiviti ); } - public async getNextNonce(request: NextNonceRequest): Promise { + public async GetNextNonce(request: NextNonceRequest): Promise { const provider = new RpcProvider({ nodeUrl: request.network.nodes[0].url }); const formattedAddress = formatAddress(request.address); @@ -202,153 +245,39 @@ export class StarknetBlockchainActivities implements IStarknetBlockchainActiviti } } - public async PublishTransaction(request: StarknetPublishTransactionRequest): Promise { - let result: string; - - const privateKey = await new PrivateKeyRepository().getAsync(request.fromAddress); - - const provider = new RpcProvider({ - nodeUrl: request.network.nodes[0].url - }); - - const account = new Account(provider, request.fromAddress, privateKey, '1'); - - var transferCall: Call = JSON.parse(request.callData); - - const compiledCallData = transaction.getExecuteCalldata([transferCall], await account.getCairoVersion()); - - const args: CalcV2InvokeTxHashArgs = { - senderAddress: request.fromAddress, - version: ETransactionVersion2.V1, - compiledCalldata: compiledCallData, - maxFee: request.fee.FixedFeeData.FeeInWei, - chainId: request.network.chainId as constants.StarknetChainId, - nonce: request.nonce - }; - - const calcualtedTxHash = hash.calculateInvokeTransactionHash(args); - - try { - - const executeResponse = await account.execute( - [transferCall], - undefined, - { - maxFee: request.fee.FixedFeeData.FeeInWei, - nonce: request.nonce - }, - ); - - result = executeResponse.transaction_hash; - - if (!result || !result.startsWith("0x")) { - throw new Error(`Withdrawal response didn't contain a correct transaction hash. Response: ${JSON.stringify(executeResponse)}`); - } - - return result; - } - catch (error) { - const nonceInfo = ParseNonces(error?.message); - - if (nonceInfo && nonceInfo.providedNonce < nonceInfo.expectedNonce) { - return calcualtedTxHash; - } - - throw error; - } - } - - public async BuildTransaction(request: TransactionBuilderRequest): Promise { - try { - switch (request.type) { - case TransactionType.HTLCLock: - return createLockCallData(request.network, request.prepareArgs); - case TransactionType.HTLCRedeem: - return createRedeemCallData(request.network, request.prepareArgs); - case TransactionType.HTLCRefund: - return createRefundCallData(request.network, request.prepareArgs); - case TransactionType.HTLCAddLockSig: - return createAddLockSigCallData(request.network, request.prepareArgs); - case TransactionType.Approve: - return createApproveCallData(request.network, request.prepareArgs); - case TransactionType.Transfer: - return createTransferCallData(request.network, request.prepareArgs); - case TransactionType.HTLCCommit: - return createCommitCallData(request.network, request.prepareArgs); - default: - throw new Error(`Unknown function name ${request.type}`); - } - } - catch (error) { - throw error; - } - } + public async PublishTransaction(request: PublishTransactionRequest): Promise { - public async GetBalance(request: BalanceRequest): Promise { - try { - const token = request.network.tokens.find(t => t.symbol === request.asset); + const invocation: Invocation = JSON.parse(request.signedRawData); + const nodeUrl = request.network.nodes[0].url; - if (!token) { - throw new Error(`Token not found for network ${request.network.name} and asset ${request.asset}`); - } - - const provider = new RpcProvider({ - nodeUrl: request.network.nodes[0].url - }); + const txHash = await sendInvocation(nodeUrl, invocation); - const erc20 = new Contract(erc20Json as Abi, token.contract, provider); - const balanceResult = await erc20.balanceOf(request.address); - const balanceInWei = BigNumber.from(uint256.uint256ToBN(balanceResult.balance as any).toString()); - - let result: BalanceResponse = { - amount: Number(balanceInWei) - } - - return result; - } - catch (error) { - throw error; - } + return txHash; } - public async SimulateTransaction(request: StarknetPublishTransactionRequest): Promise { - - const privateKey = await new PrivateKeyRepository().getAsync(request.fromAddress); + public async SimulateTransaction(request: SimulateTransactionRequest): Promise { const provider = new RpcProvider({ nodeUrl: request.network.nodes[0].url }); - const account = new Account(provider, request.fromAddress, privateKey, '1'); - - var transferCall: Call = JSON.parse(request.callData); + const invocation: Invocation = JSON.parse(request.signedRawData); - const compiledCallData = transaction.getExecuteCalldata([transferCall], await account.getCairoVersion()); - - const args: CalcV2InvokeTxHashArgs = { - senderAddress: request.fromAddress, - version: ETransactionVersion2.V1, - compiledCalldata: compiledCallData, - maxFee: request.fee.FixedFeeData.FeeInWei, - chainId: request.network.chainId as constants.StarknetChainId, - nonce: request.nonce - }; - - const calcualtedTxHash = await hash.calculateInvokeTransactionHash(args); + const accountInvocations: AccountInvocations = + [ + { + type: StarknetTransactionType.INVOKE, + contractAddress: invocation.contractAddress, + entrypoint: invocation.entrypoint, + nonce: request.nonce, + signature: invocation.signature + } + ]; try { - await account.simulateTransaction( - [ - { - type: StarknetTransactionType.INVOKE, - payload: [transferCall] - } - ], - { - nonce: request.nonce - }); + await provider.getSimulateTransaction(accountInvocations); - return calcualtedTxHash; + return; } catch (error) { const nonceInfo = ParseNonces(error?.message); @@ -369,17 +298,18 @@ export class StarknetBlockchainActivities implements IStarknetBlockchainActiviti public async EstimateFee(feeRequest: EstimateFeeRequest): Promise { try { - const privateKey = await new PrivateKeyRepository().getAsync(feeRequest.fromAddress); const provider = new RpcProvider({ nodeUrl: feeRequest.network.nodes[0].url }); - const account = new Account(provider, feeRequest.fromAddress, privateKey, '1'); - - var transferCall: Call = JSON.parse(feeRequest.callData); + const transferCall: Invocation = JSON.parse(feeRequest.callData); - let feeEstimateResponse = await account.estimateFee(transferCall); + const feeEstimateResponse = await provider.getInvokeEstimateFee( + transferCall, + { + nonce: feeRequest.nonce + }); if (!feeEstimateResponse?.suggestedMaxFee) { throw new Error(`Couldn't get fee estimation for the transfer. Response: ${JSON.stringify(feeEstimateResponse)}`); @@ -393,24 +323,12 @@ export class StarknetBlockchainActivities implements IStarknetBlockchainActiviti FeeInWei: feeInWei.toString(), }; - let result: Fee = + const result: Fee = { - Asset: this.FeeSymbol, + Asset: feeRequest.network.nativeToken.symbol, FixedFeeData: fixedfeeData, } - const balanceResponse = await this.GetBalance({ - address: feeRequest.fromAddress, - network: feeRequest.network, - asset: this.FeeSymbol - }); - - const amount = feeInWei.add(BigNumber.from(feeRequest.amount)); - - if (BigNumber.from(balanceResponse.amount).lt(amount)) { - throw new Error(`Insufficient balance for fee. Balance: ${balanceResponse.amount}, Fee: ${amount}`); - } - return result; } catch (error: any) { @@ -421,6 +339,42 @@ export class StarknetBlockchainActivities implements IStarknetBlockchainActiviti } } + public async EnsureSufficientBalance(request: EnsureSufficientBalanceRequest): Promise { + + const nativeTokenAsset = request.network.nativeToken.symbol; + + const nativeTokenBalance = await this.GetBalance({ + address: request.address, + network: request.network, + asset: nativeTokenAsset + }); + + const amount = BigNumber.from(request.amount); + const feeAmount = BigNumber.from(request.feeAmount); + + if (nativeTokenAsset === request.asset) { + + if (BigNumber.from(nativeTokenBalance.amount).lt(amount.add(feeAmount))) { + throw new Error(`Insufficient balance for fee. Balance: ${nativeTokenBalance.amount} asset ${nativeTokenAsset}, Fee: ${amount.add(feeAmount)}`); + } + } + else { + const tokenBalance = await this.GetBalance({ + address: request.address, + network: request.network, + asset: request.asset + }); + + if (BigNumber.from(nativeTokenBalance.amount).lt(feeAmount)) { + throw new Error(`Insufficient balance for fee. Balance: ${nativeTokenBalance.amount} asset ${nativeTokenAsset}, Fee: ${feeAmount}`); + } + + if (BigNumber.from(tokenBalance.amount).lt(amount)) { + throw new Error(`Insufficient balance for fee. Balance: ${tokenBalance.amount} asset ${request.asset}, Fee: ${amount}`); + } + } + } + public async ValidateAddLockSignature(request: AddLockSignatureRequest): Promise { try { @@ -499,6 +453,50 @@ export class StarknetBlockchainActivities implements IStarknetBlockchainActiviti throw error; } } + + public async ComposeRawTransaction(request: ComposeRawTransactionRequest): Promise { + + const provider = new RpcProvider({ + nodeUrl: request.network.nodes[0].url + }); + + const chainId = await provider.getChainId(); + + const signerDetails: InvocationsSignerDetails = { + ...stark.v3Details({}), + walletAddress: request.address, + nonce: request.nonce, + version: "0x3", + chainId, + cairoVersion: '1', + skipValidate: false + }; + + const parsedInvocation: Invocation = JSON.parse(request.callData); + + const transferCall: Call = + { + contractAddress: parsedInvocation.contractAddress, + entrypoint: parsedInvocation.entrypoint, + calldata: parsedInvocation.calldata + }; + + const result: ComposeRawTransactionResponse = + { + signerInvocationDetails: JSON.stringify(signerDetails), + unsignedTxn: JSON.stringify(transferCall) + }; + + return result; + }; + + public async SignTransaction(request: SignTransactionRequest): Promise { + const treasuryClient = new TreasuryClient(request.signerAgentUrl); + + const response = await treasuryClient.signTransaction(request.networkType, request.signRequest); + + return response.signedTxn; + } } export function formatAddress(address: string): string { diff --git a/js/src/Blockchain/Blockchain.Starknet/Models/ComposeRawTxModels.ts b/js/src/Blockchain/Blockchain.Starknet/Models/ComposeRawTxModels.ts new file mode 100644 index 00000000..e10e844d --- /dev/null +++ b/js/src/Blockchain/Blockchain.Starknet/Models/ComposeRawTxModels.ts @@ -0,0 +1,12 @@ +import { BaseRequest } from "../../Blockchain.Abstraction/Models/BaseRequest"; + +export interface ComposeRawTransactionRequest extends BaseRequest { + callData: string, + nonce: string, + address: string +} + +export interface ComposeRawTransactionResponse { + unsignedTxn: string, + signerInvocationDetails: string +} \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Starknet/Models/EnsureSufficientBalanceModels.ts b/js/src/Blockchain/Blockchain.Starknet/Models/EnsureSufficientBalanceModels.ts new file mode 100644 index 00000000..369c5664 --- /dev/null +++ b/js/src/Blockchain/Blockchain.Starknet/Models/EnsureSufficientBalanceModels.ts @@ -0,0 +1,8 @@ +import { BaseRequest } from "../../Blockchain.Abstraction/Models/BaseRequest"; + +export interface EnsureSufficientBalanceRequest extends BaseRequest{ + address: string, + asset: string, + amount: string, + feeAmount: string +} \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Starknet/Models/StarknetTokenCommittedEvent.ts b/js/src/Blockchain/Blockchain.Starknet/Models/EventModels.ts similarity index 71% rename from js/src/Blockchain/Blockchain.Starknet/Models/StarknetTokenCommittedEvent.ts rename to js/src/Blockchain/Blockchain.Starknet/Models/EventModels.ts index 66da92e0..ed9f1fa8 100644 --- a/js/src/Blockchain/Blockchain.Starknet/Models/StarknetTokenCommittedEvent.ts +++ b/js/src/Blockchain/Blockchain.Starknet/Models/EventModels.ts @@ -1,3 +1,9 @@ +export interface TokenLockedEvent { + hashlock: bigint; + timelock: bigint; + Id: bigint; +} + export interface TokenCommittedEvent { Id: bigint; dstChain: bigint; @@ -9,5 +15,4 @@ export interface TokenCommittedEvent { tokenContract: string; srcReceiver: bigint; sender: bigint; - } - \ No newline at end of file +} diff --git a/js/src/Blockchain/Blockchain.Starknet/Models/SignTransactionRequest.ts b/js/src/Blockchain/Blockchain.Starknet/Models/SignTransactionRequest.ts new file mode 100644 index 00000000..703f2845 --- /dev/null +++ b/js/src/Blockchain/Blockchain.Starknet/Models/SignTransactionRequest.ts @@ -0,0 +1,7 @@ +import { StarknetSignTransactionRequestModel } from "../../Blockchain.Abstraction/Infrastructure/TreasuryClient/Models/StarknetSignTransactionRequestModel"; + +export interface SignTransactionRequest{ + signRequest: StarknetSignTransactionRequestModel; + networkType: string; + signerAgentUrl: string; +} \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Starknet/Models/StarknetPublishTransactionRequest .ts b/js/src/Blockchain/Blockchain.Starknet/Models/StarknetPublishTransactionRequest .ts deleted file mode 100644 index 3c68cbb0..00000000 --- a/js/src/Blockchain/Blockchain.Starknet/Models/StarknetPublishTransactionRequest .ts +++ /dev/null @@ -1,9 +0,0 @@ -import { BaseRequest } from "../../Blockchain.Abstraction/Models/BaseRequest"; -import { Fee } from "../../Blockchain.Abstraction/Models/FeesModels/Fee"; - -export interface StarknetPublishTransactionRequest extends BaseRequest { - fromAddress: string; - callData: string; - nonce: string; - fee: Fee; - } \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Starknet/Models/StarknetTokenLockedEvent.ts b/js/src/Blockchain/Blockchain.Starknet/Models/StarknetTokenLockedEvent.ts deleted file mode 100644 index 01e0893b..00000000 --- a/js/src/Blockchain/Blockchain.Starknet/Models/StarknetTokenLockedEvent.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface TokenLockedEvent { - hashlock: bigint; - timelock: bigint; - Id: bigint; - } - \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Starknet/Models/StarknetTransactioCalculationType.ts b/js/src/Blockchain/Blockchain.Starknet/Models/StarknetTransactioCalculationType.ts deleted file mode 100644 index 28d81b58..00000000 --- a/js/src/Blockchain/Blockchain.Starknet/Models/StarknetTransactioCalculationType.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { BigNumberish, Calldata, constants } from "starknet"; -import { ETransactionVersion2 } from "starknet-types-07"; - - -export type CalcV2InvokeTxHashArgs = { - senderAddress: BigNumberish; - version: ETransactionVersion2; - compiledCalldata: Calldata; - maxFee: BigNumberish; - chainId: constants.StarknetChainId; - nonce: BigNumberish; - }; \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Starknet/Models/TransactionCalculationType.ts b/js/src/Blockchain/Blockchain.Starknet/Models/TransactionCalculationType.ts new file mode 100644 index 00000000..19d76b0e --- /dev/null +++ b/js/src/Blockchain/Blockchain.Starknet/Models/TransactionCalculationType.ts @@ -0,0 +1,11 @@ +import { BigNumberish, Calldata, constants } from "starknet"; +import { ETransactionVersion2 } from "starknet-types-07"; + +export type CalcV2InvokeTxHashArgs = { + senderAddress: BigNumberish; + version: ETransactionVersion2; + compiledCalldata: Calldata; + maxFee: BigNumberish; + chainId: constants.StarknetChainId; + nonce: BigNumberish; +}; \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Starknet/Models/TransactionModels.ts b/js/src/Blockchain/Blockchain.Starknet/Models/TransactionModels.ts new file mode 100644 index 00000000..b22c547a --- /dev/null +++ b/js/src/Blockchain/Blockchain.Starknet/Models/TransactionModels.ts @@ -0,0 +1,9 @@ +import { BaseRequest } from "../../Blockchain.Abstraction/Models/BaseRequest"; + +export interface PublishTransactionRequest extends BaseRequest { + signedRawData: string; +} + +export interface SimulateTransactionRequest extends PublishTransactionRequest { + nonce: string; +} \ No newline at end of file diff --git a/js/src/Blockchain/Blockchain.Starknet/Worker/StarknetWorker.ts b/js/src/Blockchain/Blockchain.Starknet/Worker/StarknetWorker.ts index c7827779..3074343f 100644 --- a/js/src/Blockchain/Blockchain.Starknet/Worker/StarknetWorker.ts +++ b/js/src/Blockchain/Blockchain.Starknet/Worker/StarknetWorker.ts @@ -1,5 +1,4 @@ import { Worker, NativeConnection } from '@temporalio/worker'; -import * as dotenv from 'dotenv'; import 'reflect-metadata'; import { StarknetBlockchainActivities } from '../Activities/StarknetBlockchainActivities'; import { extractActivities as ExtractActivities } from '../../../TemporalHelper/ActivityParser'; @@ -7,7 +6,6 @@ import { container } from 'tsyringe'; import { AddCoreServices } from '../../Blockchain.Abstraction/Infrastructure/AddCoreServices'; export default async function run( taskQueue: string): Promise { - dotenv.config(); try { diff --git a/js/src/Blockchain/Blockchain.Starknet/Workflows/StarknetTransactionProcessor.ts b/js/src/Blockchain/Blockchain.Starknet/Workflows/StarknetTransactionProcessor.ts index 754bc6d5..fd4a4873 100644 --- a/js/src/Blockchain/Blockchain.Starknet/Workflows/StarknetTransactionProcessor.ts +++ b/js/src/Blockchain/Blockchain.Starknet/Workflows/StarknetTransactionProcessor.ts @@ -6,13 +6,13 @@ import { AlreadyClaimedExceptions } from '../../Blockchain.Abstraction/Exception import { HTLCAlreadyExistsException } from '../../Blockchain.Abstraction/Exceptions/HTLCAlreadyExistsException'; import { TransactionFailedException } from '../../Blockchain.Abstraction/Exceptions/TransactionFailedException'; import { buildProcessorId, decodeJson } from '../../Blockchain.Abstraction/Extensions/StringExtensions'; -import { AllowanceRequest } from '../../Blockchain.Abstraction/Models/AllowanceRequest'; import { TransactionResponse } from '../../Blockchain.Abstraction/Models/ReceiptModels/TransactionResponse'; import { TransactionExecutionContext } from '../../Blockchain.Abstraction/Models/TransacitonModels/TransactionExecutionContext'; import { TransactionRequest } from '../../Blockchain.Abstraction/Models/TransacitonModels/TransactionRequest'; import { HTLCLockTransactionPrepareRequest } from '../../Blockchain.Abstraction/Models/TransactionBuilderModels/HTLCLockTransactionPrepareRequest'; import { TransferPrepareRequest } from '../../Blockchain.Abstraction/Models/TransactionBuilderModels/TransferPrepareRequest'; import { TransactionType } from '../../Blockchain.Abstraction/Models/TransacitonModels/TransactionType'; +import { NetworkType } from '../../Blockchain.Abstraction/Models/Dtos/NetworkDto'; const defaultActivities = proxyActivities({ startToCloseTimeout: '1 hour', @@ -49,8 +49,16 @@ export async function StarknetTransactionProcessor( fromAddress: request.fromAddress, swapId: request.swapId, }); + try { + if (!context.nonce) { + context.nonce = await defaultActivities.GetNextNonce({ + network: request.network, + address: request.fromAddress, + }); + } + if (!context.fee) { context.fee = await nonRetryableActivities.EstimateFee({ network: request.network, @@ -59,32 +67,46 @@ export async function StarknetTransactionProcessor( fromAddress: request.fromAddress, asset: preparedTransaction.asset!, callData: preparedTransaction.data, + nonce: context.nonce }); } - if (!context.nonce) { - context.nonce = await defaultActivities.getNextNonce({ - network: request.network, + await defaultActivities.EnsureSufficientBalance( + { address: request.fromAddress, - }); - } - - const simulationTxId = await nonRetryableActivities.SimulateTransaction({ - network: request.network, - fromAddress: request.fromAddress, - nonce: context.nonce, + amount: preparedTransaction.callDataAmount, + asset: preparedTransaction.asset, + feeAmount: context.fee.FixedFeeData.FeeInWei, + network: request.network + } + ); + + const rawTx = await defaultActivities.ComposeRawTransaction({ + address: request.fromAddress, callData: preparedTransaction.data, - fee: context.fee, + network: request.network, + nonce: context.nonce }); - context.publishedTransactionIds.push(simulationTxId); + const signedRawData = await defaultActivities.SignTransaction({ + signerAgentUrl: request.signerAgentUrl, + networkType: NetworkType[request.network.type], + signRequest: { + unsignedTxn: rawTx.unsignedTxn, + signerInvocationDetails: rawTx.signerInvocationDetails, + address: request.fromAddress, + } + }); + + await nonRetryableActivities.SimulateTransaction({ + nonce: context.nonce, + network: request.network, + signedRawData: signedRawData + }); const txId = await nonRetryableActivities.PublishTransaction({ network: request.network, - fromAddress: request.fromAddress, - nonce: context.nonce, - callData: preparedTransaction.data, - fee: context.fee, + signedRawData: signedRawData }); context.publishedTransactionIds.push(txId); @@ -98,7 +120,6 @@ export async function StarknetTransactionProcessor( confirmed.amount = preparedTransaction.callDataAmount.toString(); return confirmed; - } catch (error) { if (error instanceof InvalidTimelockException && context.nonce) { @@ -138,7 +159,7 @@ export async function StarknetTransactionProcessor( } } -export async function checkAllowance(context: TransactionRequest): Promise { +async function checkAllowance(context: TransactionRequest): Promise { const lockRequest = decodeJson(context.prepareArgs); const allowance = await defaultActivities.GetSpenderAllowance( @@ -146,7 +167,7 @@ export async function checkAllowance(context: TransactionRequest): Promise network: context.network, ownerAddress: context.fromAddress!, asset: lockRequest.sourceAsset, - } as AllowanceRequest); + }); if (lockRequest.amount > allowance) { @@ -171,7 +192,7 @@ export async function checkAllowance(context: TransactionRequest): Promise }; const processorId = buildProcessorId(uuid4(), context.network.name, context.type); - + await executeChild(StarknetTransactionProcessor, { args: [approveRequest, childContext], diff --git a/js/src/index.ts b/js/src/index.ts index 75cd6dc2..d34b189c 100644 --- a/js/src/index.ts +++ b/js/src/index.ts @@ -14,9 +14,9 @@ switch (network) { case 'Fuel': fuelWorker(network); break; - case 'Aztec': - aztecWorker(network); - break; + // case 'Aztec': + // aztecWorker(network); + // break; default: console.error(`Unknown network: ${network}. Supported networks are: Starknet, Fuel.`); process.exit(1); diff --git a/treasury/src/app/treasury.types.ts b/treasury/src/app/treasury.types.ts index 27c9c4cd..935923c9 100644 --- a/treasury/src/app/treasury.types.ts +++ b/treasury/src/app/treasury.types.ts @@ -1,6 +1,6 @@ import { EVMSignRequest, EVMSignResponse } from "../treasury/evm/evm.dto"; import { BaseSignRequest, BaseSignResponse } from "./dto/base.dto"; -import { StarknetSignRequest, StarknetSignResponse } from "../treasury/starknet/starknet.dto"; +import { StarknetSignRequest } from "../treasury/starknet/starknet.dto"; import { FuelSignRequest } from "../treasury/fuel/fuel.dto"; import { AztecSignRequest } from "../treasury/aztec/aztec.dto"; @@ -11,5 +11,4 @@ export type SignRequest = | AztecSignRequest) & BaseSignRequest; export type SignResponse = - (EVMSignResponse - | StarknetSignResponse) & BaseSignResponse; + (EVMSignResponse) & BaseSignResponse; diff --git a/treasury/src/treasury/starknet/starknet.dto.ts b/treasury/src/treasury/starknet/starknet.dto.ts index af06f899..01005501 100644 --- a/treasury/src/treasury/starknet/starknet.dto.ts +++ b/treasury/src/treasury/starknet/starknet.dto.ts @@ -1,7 +1,6 @@ import { BaseSignRequest, BaseSignResponse } from "../../app/dto/base.dto"; export class StarknetSignRequest extends BaseSignRequest { -} - -export class StarknetSignResponse extends BaseSignResponse { + signerInvocationDetails: string; + type: string } \ No newline at end of file diff --git a/treasury/src/treasury/starknet/starknet.service.ts b/treasury/src/treasury/starknet/starknet.service.ts index 11c12058..99cf72d1 100644 --- a/treasury/src/treasury/starknet/starknet.service.ts +++ b/treasury/src/treasury/starknet/starknet.service.ts @@ -1,26 +1,94 @@ import { Injectable } from '@nestjs/common'; import { TreasuryService } from '../../app/interfaces/treasury.interface'; import { Network } from '../shared/networks.types'; -import { StarknetSignRequest, StarknetSignResponse } from './starknet.dto'; -import { GenerateResponse } from '../../app/dto/base.dto'; +import { StarknetSignRequest } from './starknet.dto'; +import { BaseSignResponse, GenerateResponse } from '../../app/dto/base.dto'; +import { CairoCustomEnum, CairoOption, CairoOptionVariant, Call, CallData, DeployAccountSignerDetails, ec, hash, Invocation, InvocationsSignerDetails, Signer, stark, transaction } from 'starknet'; import { PrivateKeyService } from '../../kv/vault.service'; @Injectable() export class StarknetTreasuryService extends TreasuryService { - + readonly network: Network = 'starknet'; + readonly argentXaccountClassHash = '0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f'; - constructor(privateKeyService: PrivateKeyService){ + constructor(privateKeyService: PrivateKeyService) { super(privateKeyService); } - // TODO: Implement the Starknet signing logic - sign(req: StarknetSignRequest): Promise { - throw new Error('Method not implemented.'); + async sign(request: StarknetSignRequest): Promise { + + const privateKey = await this.privateKeyService.getAsync(request.address); + const signer = new Signer(privateKey); + + // if (request.type === "Deploy") { + // const pubKey = await signer.getPubKey(); + + // const axSigner = new CairoCustomEnum({ Starknet: { pubkey: pubKey } }); + // const axGuardian = new CairoOption(CairoOptionVariant.None); + + // const AXConstructorCallData = CallData.compile({ + // owner: axSigner, + // guardian: axGuardian, + // }); + + // const AXcontractAddress = hash.calculateContractAddressFromHash( + // pubKey, + // this.argentXaccountClassHash, + // AXConstructorCallData, + // 0 + // ); + + // const deployAccountPayload = { + // classHash: this.argentXaccountClassHash, + // constructorCalldata: AXConstructorCallData, + // contractAddress: request.address, + // addressSalt: pubKey, + // }; + + // const deployDetails: DeployAccountSignerDetails = + // { + + // } + // } + //else { + const transferCalls: Call = JSON.parse(request.unsignedTxn); + const signerDetails: InvocationsSignerDetails = JSON.parse(request.signerInvocationDetails); + + const calldata = transaction.getExecuteCalldata([transferCalls], signerDetails.cairoVersion); + const signature = await signer.signTransaction([transferCalls], signerDetails); + + const response: Invocation = { + ...stark.v3Details(signerDetails), + contractAddress: request.address, + calldata, + signature, + }; + + return { signedTxn: JSON.stringify(response) }; + //} } - // TODO: Implement the Starknet address generation(if applicable) - generate(): Promise { - throw new Error('Method not implemented.'); + async generate(): Promise { + + const privateKeyAX = stark.randomAddress(); + const starkKeyPubAX = ec.starkCurve.getStarkKey(privateKeyAX); + + // Calculate future address of the ArgentX account + const axSigner = new CairoCustomEnum({ Starknet: { pubkey: starkKeyPubAX } }); + const axGuardian = new CairoOption(CairoOptionVariant.None); + const AXConstructorCallData = CallData.compile({ + owner: axSigner, + guardian: axGuardian, + }); + + const address = hash.calculateContractAddressFromHash( + starkKeyPubAX, + this.argentXaccountClassHash, + AXConstructorCallData, + 0 + ); + + return { address } } } \ No newline at end of file diff --git a/treasury/src/treasury/treasury.module.ts b/treasury/src/treasury/treasury.module.ts index bae4e137..0aed57d9 100644 --- a/treasury/src/treasury/treasury.module.ts +++ b/treasury/src/treasury/treasury.module.ts @@ -17,8 +17,8 @@ import { AztecConfigService } from './aztec/aztec.config'; AztecConfigService, { provide: TREASURIES, - useFactory: (evm, starknet, fuel, aztec) => [evm, starknet, fuel, aztec], - inject: [EvmTreasuryService, StarknetTreasuryService, FuelTreasuryService, AztecTreasuryService], + useFactory: (evm, starknet, fuel) => [evm, starknet, fuel], + inject: [EvmTreasuryService, StarknetTreasuryService, FuelTreasuryService], }, ], exports: [TREASURIES],