From de4f1de028e13663dd34a927c4baf8f18ecf192d Mon Sep 17 00:00:00 2001 From: Dani Somoza Date: Mon, 16 Dec 2024 13:56:42 +0100 Subject: [PATCH] feat: Onchain Identifier via transaction `data` and `calldata` fields (#1059) --- packages/protocol-kit/src/Safe.ts | 76 +++++++- packages/protocol-kit/src/index.ts | 2 + packages/protocol-kit/src/types/safeConfig.ts | 11 ++ .../src/utils/getProtocolKitVersion.ts | 7 + .../generateOnChainIdentifier.ts | 57 ++++++ .../tests/e2e/onChainIdentifier.test.ts | 171 ++++++++++++++++++ packages/protocol-kit/tsconfig.build.json | 3 +- packages/protocol-kit/tsconfig.json | 3 +- .../src/packs/safe-4337/Safe4337Pack.ts | 44 ++++- .../relay-kit/src/packs/safe-4337/types.ts | 8 +- .../safe-4337/utils/getRelayKitVersion.ts | 7 + packages/relay-kit/tsconfig.build.json | 3 +- packages/relay-kit/tsconfig.json | 3 +- .../create-execute-transaction.ts | 2 +- 14 files changed, 382 insertions(+), 15 deletions(-) create mode 100644 packages/protocol-kit/src/utils/getProtocolKitVersion.ts create mode 100644 packages/protocol-kit/src/utils/on-chain-tracking/generateOnChainIdentifier.ts create mode 100644 packages/protocol-kit/tests/e2e/onChainIdentifier.test.ts create mode 100644 packages/relay-kit/src/packs/safe-4337/utils/getRelayKitVersion.ts diff --git a/packages/protocol-kit/src/Safe.ts b/packages/protocol-kit/src/Safe.ts index 6b39deeb8..c578ac8af 100644 --- a/packages/protocol-kit/src/Safe.ts +++ b/packages/protocol-kit/src/Safe.ts @@ -20,6 +20,7 @@ import { getChainSpecificDefaultSaltNonce, getPredictedSafeAddressInitCode, predictSafeAddress, + toTxResult, validateSafeAccountConfig, validateSafeDeploymentConfig } from './contracts/utils' @@ -83,9 +84,11 @@ import SafeMessage from './utils/messages/SafeMessage' import semverSatisfies from 'semver/functions/satisfies' import SafeProvider from './SafeProvider' import { asHash, asHex } from './utils/types' -import { Hash, Hex } from 'viem' +import { Hash, Hex, SendTransactionParameters } from 'viem' import getPasskeyOwnerAddress from './utils/passkeys/getPasskeyOwnerAddress' import createPasskeyDeploymentTransaction from './utils/passkeys/createPasskeyDeploymentTransaction' +import generateOnChainIdentifier from './utils/on-chain-tracking/generateOnChainIdentifier' +import getProtocolKitVersion from './utils/getProtocolKitVersion' const EQ_OR_GT_1_4_1 = '>=1.4.1' const EQ_OR_GT_1_3_0 = '>=1.3.0' @@ -102,6 +105,9 @@ class Safe { #MAGIC_VALUE = '0x1626ba7e' #MAGIC_VALUE_BYTES = '0x20c13b0b' + // on-chain Analytics + #onchainIdentifier: string = '' + /** * Creates an instance of the Safe Core SDK. * @param config - Ethers Safe configuration @@ -126,7 +132,17 @@ class Safe { * @throws "MultiSendCallOnly contract is not deployed on the current network" */ async #initializeProtocolKit(config: SafeConfig) { - const { provider, signer, isL1SafeSingleton, contractNetworks } = config + const { provider, signer, isL1SafeSingleton, contractNetworks, onchainAnalytics } = config + + if (onchainAnalytics?.project) { + const { project, platform } = onchainAnalytics + this.#onchainIdentifier = generateOnChainIdentifier({ + project, + platform, + tool: 'protocol-kit', + toolVersion: getProtocolKitVersion() + }) + } this.#safeProvider = await SafeProvider.init({ provider, @@ -1340,6 +1356,32 @@ class Safe { const signerAddress = await this.#safeProvider.getSignerAddress() + if (this.#onchainIdentifier) { + const encodedTransaction = await this.getEncodedTransaction(signedSafeTransaction) + + const transaction = { + to: await this.getAddress(), + value: 0n, + data: encodedTransaction + this.#onchainIdentifier + } + + const signer = await this.#safeProvider.getExternalSigner() + + if (!signer) { + throw new Error('A signer must be set') + } + + const hash = await signer.sendTransaction({ + ...transaction, + account: signer.account, + ...options + } as SendTransactionParameters) + + const provider = this.#safeProvider.getExternalProvider() + + return toTxResult(provider, hash, options) + } + const txResponse = await this.#contractManager.safeContract.execTransaction( signedSafeTransaction, { @@ -1466,6 +1508,14 @@ class Safe { // we create the deployment transaction const safeDeploymentTransaction = await this.createSafeDeploymentTransaction() + // remove the onchain idendifier if it is included + if (safeDeploymentTransaction.data.endsWith(this.#onchainIdentifier)) { + safeDeploymentTransaction.data = safeDeploymentTransaction.data.replace( + this.#onchainIdentifier, + '' + ) + } + // First transaction of the batch: The Safe deployment Transaction const safeDeploymentBatchTransaction = { to: safeDeploymentTransaction.to, @@ -1486,7 +1536,11 @@ class Safe { const transactions = [safeDeploymentBatchTransaction, safeBatchTransaction] // this is the transaction with the batch - const safeDeploymentBatch = await this.createTransactionBatch(transactions, transactionOptions) + const safeDeploymentBatch = await this.createTransactionBatch( + transactions, + transactionOptions, + !!this.#onchainIdentifier // include the on chain identifier + ) return safeDeploymentBatch } @@ -1561,6 +1615,10 @@ class Safe { ]) } + if (this.#onchainIdentifier) { + safeDeployTransactionData.data += this.#onchainIdentifier + } + return safeDeployTransactionData } @@ -1572,12 +1630,14 @@ class Safe { * @function createTransactionBatch * @param {MetaTransactionData[]} transactions - An array of MetaTransactionData objects to be batched together. * @param {TransactionOption} [transactionOptions] - Optional TransactionOption object to specify additional options for the transaction batch. + * @param {boolean} [includeOnchainIdentifier=false] - A flag indicating whether to append the onchain identifier to the data field of the resulting transaction. * @returns {Promise} A Promise that resolves with the created transaction batch. * */ async createTransactionBatch( transactions: MetaTransactionData[], - transactionOptions?: TransactionOptions + transactionOptions?: TransactionOptions, + includeOnchainIdentifier: boolean = false ): Promise { // we use the MultiSend contract to create the batch, see: https://github.com/safe-global/safe-contracts/blob/main/contracts/libraries/MultiSendCallOnly.sol const multiSendCallOnlyContract = this.#contractManager.multiSendCallOnlyContract @@ -1594,6 +1654,10 @@ class Safe { data: batchData } + if (includeOnchainIdentifier) { + transactionBatch.data += this.#onchainIdentifier + } + return transactionBatch } @@ -1701,6 +1765,10 @@ class Safe { return getContractInfo(contractAddress) } + getOnchainIdentifier(): string { + return this.#onchainIdentifier + } + /** * This method creates a signer to be used with the init method * @param {Credential} credential - The credential to be used to create the signer. Can be generated in the web with navigator.credentials.create diff --git a/packages/protocol-kit/src/index.ts b/packages/protocol-kit/src/index.ts index 9c502e2e0..9e895e60f 100644 --- a/packages/protocol-kit/src/index.ts +++ b/packages/protocol-kit/src/index.ts @@ -66,6 +66,7 @@ import { } from './utils/eip-712' import { createPasskeyClient } from './utils/passkeys/PasskeyClient' import getPasskeyOwnerAddress from './utils/passkeys/getPasskeyOwnerAddress' +import generateOnChainIdentifier from './utils/on-chain-tracking/generateOnChainIdentifier' export { estimateTxBaseGas, @@ -80,6 +81,7 @@ export { EthSafeSignature, MultiSendCallOnlyBaseContract, MultiSendBaseContract, + generateOnChainIdentifier, PREDETERMINED_SALT_NONCE, SafeBaseContract, SafeProxyFactoryBaseContract, diff --git a/packages/protocol-kit/src/types/safeConfig.ts b/packages/protocol-kit/src/types/safeConfig.ts index 11d606ab9..7c330ceaf 100644 --- a/packages/protocol-kit/src/types/safeConfig.ts +++ b/packages/protocol-kit/src/types/safeConfig.ts @@ -41,6 +41,13 @@ type SafeConfigWithPredictedSafeProps = { predictedSafe: PredictedSafeProps } +export type OnchainAnalyticsProps = { + /** project - The project that is using the SDK */ + project?: string + /** platform - The platform that is using the SDK */ + platform?: string +} + export type SafeConfigProps = { provider: SafeProviderConfig['provider'] signer?: SafeProviderConfig['signer'] @@ -48,6 +55,8 @@ export type SafeConfigProps = { isL1SafeSingleton?: boolean /** contractNetworks - Contract network configuration */ contractNetworks?: ContractNetworksConfig + // on-chain analytics + onchainAnalytics?: OnchainAnalyticsProps } export type SafeConfigWithSafeAddress = SafeConfigProps & SafeConfigWithSafeAddressProps @@ -75,6 +84,8 @@ type ConnectSafeConfigProps = { isL1SafeSingleton?: boolean /** contractNetworks - Contract network configuration */ contractNetworks?: ContractNetworksConfig + // on-chain analytics + onchainAnalytics?: OnchainAnalyticsProps } export type ConnectSafeConfigWithSafeAddress = ConnectSafeConfigProps & diff --git a/packages/protocol-kit/src/utils/getProtocolKitVersion.ts b/packages/protocol-kit/src/utils/getProtocolKitVersion.ts new file mode 100644 index 000000000..3abd3bdb4 --- /dev/null +++ b/packages/protocol-kit/src/utils/getProtocolKitVersion.ts @@ -0,0 +1,7 @@ +import packageJson from '../../package.json' + +function getProtocolKitVersion(): string { + return packageJson.version +} + +export default getProtocolKitVersion diff --git a/packages/protocol-kit/src/utils/on-chain-tracking/generateOnChainIdentifier.ts b/packages/protocol-kit/src/utils/on-chain-tracking/generateOnChainIdentifier.ts new file mode 100644 index 000000000..aee82d29f --- /dev/null +++ b/packages/protocol-kit/src/utils/on-chain-tracking/generateOnChainIdentifier.ts @@ -0,0 +1,57 @@ +import { keccak256, toHex } from 'viem' + +/** + * Generates a hash from the given input string and truncates it to the specified size. + * + * @param {string} input - The input string to be hashed. + * @param {number} size - The number of bytes to take from the end of the hash. + * @returns {string} A hexadecimal string representation of the truncated hash, without the `0x` prefix. + */ +export function generateHash(input: string, size: number): string { + const fullHash = keccak256(toHex(input)) + return toHex(fullHash.slice(-size)).replace('0x', '') // Take the last X bytes +} + +export type OnChainIdentifierParamsType = { + project: string + platform?: string + tool: string + toolVersion: string +} + +/** + * Generates an on-chain identifier for tracking transactions on the blockchain. + * This identifier includes hashed metadata such as the project name, platform, tool, and tool version. + * + * @param {Object} params - An object containing the metadata for generating the on-chain identifier. + * @param {string} params.project - The name of the project initiating the transaction. + * @param {string} [params.platform='Web'] - The platform from which the transaction originates (e.g., "Web", "Mobile", "Safe App", "Widget"...). + * @param {string} params.tool - The tool used to generate the transaction (e.g., "protocol-kit"). + * @param {string} params.toolVersion - The version of the tool used to generate the transaction. + * @returns {string} A string representing the on-chain identifier, composed of multiple hashed segments. + * + * @example + * const identifier = generateOnChainIdentifier({ + * project: 'MyProject', + * platform: 'Mobile', + * tool: 'protocol-kit', + * toolVersion: '4.0.0' + * }) + */ +function generateOnChainIdentifier({ + project, + platform = 'Web', + tool, + toolVersion +}: OnChainIdentifierParamsType): string { + const identifierPrefix = '5afe' + const identifierVersion = '00' // first version + const projectHash = generateHash(project, 20) // Take the last 20 bytes + const platformHash = generateHash(platform, 3) // Take the last 3 bytes + const toolHash = generateHash(tool, 3) // Take the last 3 bytes + const toolVersionHash = generateHash(toolVersion, 3) // Take the last 3 bytes + + return `${identifierPrefix}${identifierVersion}${projectHash}${platformHash}${toolHash}${toolVersionHash}` +} + +export default generateOnChainIdentifier diff --git a/packages/protocol-kit/tests/e2e/onChainIdentifier.test.ts b/packages/protocol-kit/tests/e2e/onChainIdentifier.test.ts new file mode 100644 index 000000000..b45f47769 --- /dev/null +++ b/packages/protocol-kit/tests/e2e/onChainIdentifier.test.ts @@ -0,0 +1,171 @@ +import { setupTests, safeVersionDeployed } from '@safe-global/testing-kit' +import Safe, { + generateOnChainIdentifier, + OnchainAnalyticsProps, + PredictedSafeProps, + SafeAccountConfig +} from '@safe-global/protocol-kit/index' +import chai from 'chai' +import Sinon from 'sinon' +import chaiAsPromised from 'chai-as-promised' + +import { generateHash } from '@safe-global/protocol-kit/utils/on-chain-tracking/generateOnChainIdentifier' +import getProtocolKitVersion, * as getProtocolKitVersionModule from '@safe-global/protocol-kit/utils/getProtocolKitVersion' +import { getEip1193Provider } from './utils/setupProvider' +import { waitSafeTxReceipt } from './utils/transactions' + +chai.use(chaiAsPromised) + +describe('On-chain analytics', () => { + const provider = getEip1193Provider() + + describe('generateOnChainIdentifier fn', () => { + it('should return the correct on-chain identifier format', async () => { + const project = 'Test e2e Project' + const platform = 'Web' + const tool = 'protocol-kit' + const toolVersion = '1.0.0' + + const onChainIdentifier = generateOnChainIdentifier({ project, platform, tool, toolVersion }) + + const identifierPrefix = '5afe' + const identifierVersion = '00' + + chai.expect(onChainIdentifier.startsWith(identifierPrefix)).to.be.true + chai.expect(onChainIdentifier.substring(4, 6)).to.equals(identifierVersion) + chai.expect(onChainIdentifier.substring(6, 46)).to.equals(generateHash(project, 20)) + chai.expect(onChainIdentifier.substring(46, 52)).to.equals(generateHash(platform, 3)) + chai.expect(onChainIdentifier.substring(52, 58)).to.equals(generateHash(tool, 3)) + chai.expect(onChainIdentifier.substring(58, 64)).to.equals(generateHash(toolVersion, 3)) + }) + }) + + describe('getOnchainIdentifier method', () => { + it('should return the on-chain identifier when provided', async () => { + const onchainAnalytics: OnchainAnalyticsProps = { + project: 'Test e2e Project', + platform: 'Web' + } + + const stub = Sinon.stub(getProtocolKitVersionModule, 'default').returns('5.0.4') + + const { safe, contractNetworks } = await setupTests() + const safeAddress = safe.address + + const protocolKit = await Safe.init({ + provider, + safeAddress, + contractNetworks, + onchainAnalytics + }) + + const onChainIdentifier = '5afe003861653435366632366138366164643038373864646561393238653366' + + chai.expect(onChainIdentifier).to.equals(protocolKit.getOnchainIdentifier()) + stub.restore() + }) + + it('should return an empty string when no onchain Analiticts is provided', async () => { + const { safe, contractNetworks } = await setupTests() + const safeAddress = safe.address + + const protocolKit = await Safe.init({ + provider, + safeAddress, + contractNetworks + }) + + chai.expect(protocolKit.getOnchainIdentifier()).to.empty + }) + }) + + describe('Tracking Safe Deployment on-chain via the transaction data field', () => { + it('should append the on-chain identifier to the deployment transaction data field', async () => { + const onchainAnalytics: OnchainAnalyticsProps = { + project: 'Test e2e Project', + platform: 'Web' + } + + const { accounts, contractNetworks } = await setupTests() + const [account1, account2] = accounts + const owners = [account1.address, account2.address] + const threshold = 1 + const safeAccountConfig: SafeAccountConfig = { owners, threshold } + const predictedSafe: PredictedSafeProps = { + safeAccountConfig, + safeDeploymentConfig: { + safeVersion: safeVersionDeployed + } + } + + const protocolKit = await Safe.init({ + provider, + predictedSafe, + contractNetworks, + onchainAnalytics + }) + + const deploymentTransaction = await protocolKit.createSafeDeploymentTransaction() + + // toolVersion is dynamic (currrent protocol-kit version) + const toolVersion = getProtocolKitVersion() + const toolHash = generateHash(toolVersion, 3) + + const onChainIdentifier = + '5afe003861653435366632366138366164643038373864646561393238' + toolHash + + chai.expect(onChainIdentifier).to.equals(protocolKit.getOnchainIdentifier()) + chai.expect(deploymentTransaction.data.endsWith(onChainIdentifier)).to.be.true + }) + }) + + describe('Tracking Safe transactions on-chain via the transaction data field', () => { + it('should append the on-chain identifier to the execTransaction data field', async () => { + const onchainAnalytics: OnchainAnalyticsProps = { + project: 'Test e2e Project', + platform: 'Web' + } + + const { safe, contractNetworks } = await setupTests() + const safeAddress = safe.address + + const protocolKit = await Safe.init({ + provider, + safeAddress, + contractNetworks, + onchainAnalytics + }) + + const testTransaction = { + to: safeAddress, + value: '0', + data: '0x' + } + + const safeTransaction = await protocolKit.createTransaction({ + transactions: [testTransaction] + }) + + const isValidTransaction = await protocolKit.isValidTransaction(safeTransaction) + chai.expect(isValidTransaction).to.be.eq(true) + + const transactionResponse = await protocolKit.executeTransaction(safeTransaction) + + await waitSafeTxReceipt(transactionResponse) + + const transaction = await protocolKit + .getSafeProvider() + .getTransaction(transactionResponse.hash) + + // toolVersion is dynamic (currrent protocol-kit version) + const toolVersion = getProtocolKitVersion() + const toolHash = generateHash(toolVersion, 3) + + const onChainIdentifier = + '5afe003861653435366632366138366164643038373864646561393238' + toolHash + + chai.expect(onChainIdentifier).to.equals(protocolKit.getOnchainIdentifier()) + chai.expect(transaction.input.endsWith(onChainIdentifier)).to.be.true + }) + }) +}) diff --git a/packages/protocol-kit/tsconfig.build.json b/packages/protocol-kit/tsconfig.build.json index c05e497c4..416bcce06 100644 --- a/packages/protocol-kit/tsconfig.build.json +++ b/packages/protocol-kit/tsconfig.build.json @@ -1,8 +1,9 @@ { "extends": "../../tsconfig.settings.json", "compilerOptions": { + "resolveJsonModule": true, "composite": true, "outDir": "dist" }, - "include": ["src/**/*"] + "include": ["src/**/*", "package.json"] } diff --git a/packages/protocol-kit/tsconfig.json b/packages/protocol-kit/tsconfig.json index 5f6bc90a7..77c78ede6 100644 --- a/packages/protocol-kit/tsconfig.json +++ b/packages/protocol-kit/tsconfig.json @@ -1,8 +1,9 @@ { "extends": "../../tsconfig.settings.json", "compilerOptions": { + "resolveJsonModule": true, "composite": true, "outDir": "dist" }, - "include": ["src/**/*", "tests/**/*", "hardhat/**/*", "hardhat.config.ts"] + "include": ["package.json", "src/**/*", "tests/**/*", "hardhat/**/*", "hardhat.config.ts"] } diff --git a/packages/relay-kit/src/packs/safe-4337/Safe4337Pack.ts b/packages/relay-kit/src/packs/safe-4337/Safe4337Pack.ts index aa045d232..e45507f4a 100644 --- a/packages/relay-kit/src/packs/safe-4337/Safe4337Pack.ts +++ b/packages/relay-kit/src/packs/safe-4337/Safe4337Pack.ts @@ -5,7 +5,8 @@ import Safe, { encodeMultiSendData, getMultiSendContract, PasskeyClient, - SafeProvider + SafeProvider, + generateOnChainIdentifier } from '@safe-global/protocol-kit' import { RelayKitBasePack } from '@safe-global/relay-kit/RelayKitBasePack' import { @@ -52,6 +53,7 @@ import { } from './utils' import { entryPointToSafeModules, EQ_OR_GT_0_3_0 } from './utils/entrypoint' import { PimlicoFeeEstimator } from './estimators/PimlicoFeeEstimator' +import getRelayKitVersion from './utils/getRelayKitVersion' const MAX_ERC20_AMOUNT_TO_APPROVE = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn @@ -87,6 +89,8 @@ export class Safe4337Pack extends RelayKitBasePack<{ #paymasterOptions?: PaymasterOptions + #onchainIdentifier: string = '' + /** * Creates an instance of the Safe4337Pack. * @@ -100,7 +104,8 @@ export class Safe4337Pack extends RelayKitBasePack<{ paymasterOptions, entryPointAddress, safe4337ModuleAddress, - safeWebAuthnSharedSignerAddress + safeWebAuthnSharedSignerAddress, + onchainAnalytics }: Safe4337Options) { super(protocolKit) @@ -111,6 +116,16 @@ export class Safe4337Pack extends RelayKitBasePack<{ this.#ENTRYPOINT_ADDRESS = entryPointAddress this.#SAFE_4337_MODULE_ADDRESS = safe4337ModuleAddress this.#SAFE_WEBAUTHN_SHARED_SIGNER_ADDRESS = safeWebAuthnSharedSignerAddress || '0x' + + if (onchainAnalytics?.project) { + const { project, platform } = onchainAnalytics + this.#onchainIdentifier = generateOnChainIdentifier({ + project, + platform, + tool: 'relay-kit', + toolVersion: getRelayKitVersion() + }) + } } /** @@ -124,7 +139,16 @@ export class Safe4337Pack extends RelayKitBasePack<{ * @return {Promise} The Promise object that will be resolved into an instance of Safe4337Pack. */ static async init(initOptions: Safe4337InitOptions): Promise { - const { provider, signer, options, bundlerUrl, customContracts, paymasterOptions } = initOptions + const { + provider, + signer, + options, + bundlerUrl, + customContracts, + paymasterOptions, + onchainAnalytics + } = initOptions + let protocolKit: Safe const bundlerClient = getEip4337BundlerProvider(bundlerUrl) const chainId = await bundlerClient.request({ method: RPC_4337_CALLS.CHAIN_ID }) @@ -329,7 +353,8 @@ export class Safe4337Pack extends RelayKitBasePack<{ payment: 0, paymentReceiver: zeroAddress } - } + }, + onchainAnalytics }) } @@ -372,7 +397,8 @@ export class Safe4337Pack extends RelayKitBasePack<{ bundlerUrl, entryPointAddress: selectedEntryPoint!, safe4337ModuleAddress, - safeWebAuthnSharedSignerAddress + safeWebAuthnSharedSignerAddress, + onchainAnalytics }) } @@ -526,6 +552,10 @@ export class Safe4337Pack extends RelayKitBasePack<{ signature: '0x' } + if (this.#onchainIdentifier) { + userOperation.callData += this.#onchainIdentifier + } + const isSafeDeployed = await this.protocolKit.isSafeDeployed() if (!isSafeDeployed) { @@ -799,4 +829,8 @@ export class Safe4337Pack extends RelayKitBasePack<{ ] }) } + + getOnchainIdentifier(): string { + return this.#onchainIdentifier + } } diff --git a/packages/relay-kit/src/packs/safe-4337/types.ts b/packages/relay-kit/src/packs/safe-4337/types.ts index a64bda523..77ba49ae0 100644 --- a/packages/relay-kit/src/packs/safe-4337/types.ts +++ b/packages/relay-kit/src/packs/safe-4337/types.ts @@ -1,5 +1,9 @@ import { Account, Address, Chain, Hash, Hex, PublicClient, PublicRpcSchema, Transport } from 'viem' -import Safe, { DeploymentType, SafeProviderConfig } from '@safe-global/protocol-kit' +import Safe, { + DeploymentType, + SafeProviderConfig, + OnchainAnalyticsProps +} from '@safe-global/protocol-kit' import { EstimateGasData, MetaTransactionData, @@ -50,6 +54,7 @@ export type Safe4337InitOptions = { } options: ExistingSafeOptions | PredictedSafeOptions paymasterOptions?: PaymasterOptions + onchainAnalytics?: OnchainAnalyticsProps } export type Safe4337Options = { @@ -61,6 +66,7 @@ export type Safe4337Options = { entryPointAddress: string safe4337ModuleAddress: string safeWebAuthnSharedSignerAddress?: string + onchainAnalytics?: OnchainAnalyticsProps } export type Safe4337CreateTransactionProps = { diff --git a/packages/relay-kit/src/packs/safe-4337/utils/getRelayKitVersion.ts b/packages/relay-kit/src/packs/safe-4337/utils/getRelayKitVersion.ts new file mode 100644 index 000000000..8f90e8f67 --- /dev/null +++ b/packages/relay-kit/src/packs/safe-4337/utils/getRelayKitVersion.ts @@ -0,0 +1,7 @@ +import packageJson from '../../../../package.json' + +function getRelayKitVersion(): string { + return packageJson.version +} + +export default getRelayKitVersion diff --git a/packages/relay-kit/tsconfig.build.json b/packages/relay-kit/tsconfig.build.json index cc22498f1..9c287382b 100644 --- a/packages/relay-kit/tsconfig.build.json +++ b/packages/relay-kit/tsconfig.build.json @@ -1,9 +1,10 @@ { "extends": "../../tsconfig.settings.json", "compilerOptions": { + "resolveJsonModule": true, "composite": true, "outDir": "dist" }, - "include": ["src/**/*"], + "include": ["src/**/*", "package.json"], "exclude": ["src/**/*.test.ts", "src/**/*.test-d.ts"] } diff --git a/packages/relay-kit/tsconfig.json b/packages/relay-kit/tsconfig.json index c05e497c4..416bcce06 100644 --- a/packages/relay-kit/tsconfig.json +++ b/packages/relay-kit/tsconfig.json @@ -1,8 +1,9 @@ { "extends": "../../tsconfig.settings.json", "compilerOptions": { + "resolveJsonModule": true, "composite": true, "outDir": "dist" }, - "include": ["src/**/*"] + "include": ["src/**/*", "package.json"] } diff --git a/playground/protocol-kit/create-execute-transaction.ts b/playground/protocol-kit/create-execute-transaction.ts index 52e00230b..e4a9a3b9a 100644 --- a/playground/protocol-kit/create-execute-transaction.ts +++ b/playground/protocol-kit/create-execute-transaction.ts @@ -37,7 +37,7 @@ async function main() { console.log(' - Version: ', await safe.getContractVersion()) console.log(' - Threshold: ', await safe.getThreshold(), '\n') - // Create transaction + // Create rejection transaction const safeTransactionData: SafeTransactionDataPartial = { to: config.SAFE_ADDRESS, value: '1000000000000000', // 0.001 ether