diff --git a/pages/reference-sdk-protocol-kit/_meta.json b/pages/reference-sdk-protocol-kit/_meta.json index 9f06d949..2641e01b 100644 --- a/pages/reference-sdk-protocol-kit/_meta.json +++ b/pages/reference-sdk-protocol-kit/_meta.json @@ -16,5 +16,6 @@ "messages": "Messages", "safe-modules": "Safe Modules", "safe-guards": "Safe Guards", - "fallback-handler": "Fallback Handler" + "fallback-handler": "Fallback Handler", + "onchain-tracking": "On-chain Tracking" } diff --git a/pages/reference-sdk-protocol-kit/onchain-tracking/_meta.json b/pages/reference-sdk-protocol-kit/onchain-tracking/_meta.json new file mode 100644 index 00000000..2b00d2eb --- /dev/null +++ b/pages/reference-sdk-protocol-kit/onchain-tracking/_meta.json @@ -0,0 +1,3 @@ +{ + "getOnchainIdentifier": "getOnchainIdentifier" +} \ No newline at end of file diff --git a/pages/reference-sdk-protocol-kit/onchain-tracking/getOnchainIdentifier.mdx b/pages/reference-sdk-protocol-kit/onchain-tracking/getOnchainIdentifier.mdx new file mode 100644 index 00000000..f4a79f9d --- /dev/null +++ b/pages/reference-sdk-protocol-kit/onchain-tracking/getOnchainIdentifier.mdx @@ -0,0 +1,44 @@ +import { Tabs } from 'nextra/components' + +# `getOnchainIdentifier` + +Returns the on-chain identifier generated internally. This identifier is appended to the `data` field of transactions to enable on-chain tracking. + +## Usage + +{/* */} + + + + ```typescript + import { protocolKit } from './setup.ts' + + const onchainIdentifier = await protocolKit.getOnchainIdentifier() + + console.log(onchainIdentifier) // e.g., '5afe006562303761323539616336346466346135306537646561393238383963' + ``` + + + ```typescript + import Safe from '@safe-global/protocol-kit' + + export const protocolKit = Safe.init({ + // ... + onchainAnalytics: { + project: 'Cow Swap', // Specify your project name + platform: 'Web' // Optional platform + } + }) + ``` + + + +{/* */} + +## Returns + +`string` + +The on-chain identifier in hexadecimal format (`5afe00...`), which includes hashed metadata such as project name, platform, tool, and tool version. + +For more details about the identifier format, please refer to the [On-chain identifier](../../sdk/onchain-tracking.mdx#on-chain-identifier-format) section. diff --git a/pages/sdk/_meta.json b/pages/sdk/_meta.json index 982acac7..3d9dbec9 100644 --- a/pages/sdk/_meta.json +++ b/pages/sdk/_meta.json @@ -22,5 +22,6 @@ "title": "Integrations" }, "signers": "Signers", + "onchain-tracking": "On-chain Tracking", "onramp": "Onramp" } diff --git a/pages/sdk/onchain-tracking.mdx b/pages/sdk/onchain-tracking.mdx new file mode 100644 index 00000000..7ae2217d --- /dev/null +++ b/pages/sdk/onchain-tracking.mdx @@ -0,0 +1,186 @@ +import { Tabs, Steps } from 'nextra/components' + +# On-chain Tracking + +We aim to understand better and recognise our key contributors who are driving the adoption of smart accounts within our ecosystem. + +Implementing a Safe on-chain identifier enables tracking of complex data, such as whether a Safe transaction is executed via our SDK or another, whether it originates from a platform like a Safe App or widget (for example, the CoW Swap widget in our Safe interface), the tool version, the project, and more. + +By submitting your on-chain identifier through the form provided at the end of this page, you will help us accurately attribute activity and allow us to return value to our Ecosystem Partners in the future. + +## On-chain identifier format + +The identifiers used to track Safe deployments and transactions are 50 bytes in length and follow the format below: + +`5afe` `00` `6363643438383836663461336661366162653539` `646561` `393238` `653366` + +Check the last 50 bytes of the `data` field in this [example transaction](https://sepolia.etherscan.io/tx/0xe0192eedd1fc2d06be0561d57380d610dd6d162af0f3cfbd6c08f9062d738761) to see how the identifier appears after the transaction is executed. + +### Prefix hash + +- **Type:** `2 bytes` +- **Example:** `5afe` + +Static prefix to identify the Safe on-chain identifier. + +### Version hash + +- **Type:** `1 byte` +- **Example:** `00` + +Version number of the Safe on-chain identifier format. + +### Project hash + +- **Type:** `20 bytes` +- **Example:** `6363643438383836663461336661366162653539` + +Truncated hash of the project's name (for example, "Gnosis", "CoW Swap"). + +### Platform hash + +- **Type:** `3 bytes` +- **Example:** `646561` + +Truncated hash of the platform's name (for example, "Web", "Mobile", "Safe App", "Widget"). + +### Tool hash + +- **Type:** `3 bytes` +- **Example:** `393238` + +Truncated hash of the tool's name (for example, "protocol-kit", "relay-kit", or any custom tool built by projects). + +### Tool version hash + +- **Type:** `3 bytes` +- **Example:** `653366` + +Truncated hash of the tool's version (for example, "1.0.0", "1.0.1"). + +## Steps + +The on-chain identifier allows tracking the deployment of Safe accounts, the execution of Safe transactions, and the execution of Safe user operations: + + + + ### Track Safe deployments + + Safe deployments can be tracked by assigning an on-chain identifier to the [`paymentReceiver`](../reference-smart-account/setup/setup.mdx#paymentreceiver) or [`saltNonce`](https://github.com/safe-global/safe-smart-account/blob/main/contracts/proxies/SafeProxyFactory.sol#L55) properties during the Safe configuration and deployment. + + If you use the [Protocol Kit](../sdk/protocol-kit.mdx) or the [Relay Kit](../sdk/relay-kit.mdx) to deploy a Safe, adding the `onchainAnalytics` property to the initialization method will automatically handle this. The deployment transaction will include the identifier. + + {/* */} + + + + ```typescript + import Safe, { OnchainAnalyticsProps } from '@safe-global/protocol-kit' + + const onchainAnalytics: OnchainAnalyticsProps = { + project: 'YOUR_PROJECT_NAME' + platform: 'CURRENT_PLATFORM' // Optional + } + + const protocolKit = await Safe.init({ + // ... + onchainAnalytics + }) + + // Execute the deployment + ``` + + + ```typescript + import { Safe4337Pack } from '@safe-global/relay-kit' + import { OnchainAnalyticsProps } from '@safe-global/protocol-kit' + + const onchainAnalytics: OnchainAnalyticsProps = { + project: 'YOUR_PROJECT_NAME' + platform: 'CURRENT_PLATFORM' // Optional + } + + const safe4337Pack = await Safe4337Pack.init({ + // ... + onchainAnalytics + }) + + // Execute the deployment + ``` + + + + {/* */} + + ### Track Safe transactions + + Safe transactions can be tracked by concatenating the on-chain identifier at the end of the transaction `data` or user operation `callData` properties. + + If you use the [Protocol Kit](../sdk/protocol-kit.mdx) or the [Relay Kit](../sdk/relay-kit.mdx) to execute the Safe transactions, adding the `onchainAnalytics` property to the initialization method will automatically handle this. The Safe transactions will include the identifier. + + {/* */} + + + + ```typescript + import Safe, { OnchainAnalyticsProps } from '@safe-global/protocol-kit' + + const onchainAnalytics: OnchainAnalyticsProps = { + project: 'YOUR_PROJECT_NAME' + platform: 'CURRENT_PLATFORM' // Optional + } + + const protocolKit = await Safe.init({ + // ... + onchainAnalytics + }) + + // Execute the transaction + ``` + + + ```typescript + import { Safe4337Pack } from '@safe-global/relay-kit' + import { OnchainAnalyticsProps } from '@safe-global/protocol-kit' + + const onchainAnalytics: OnchainAnalyticsProps = { + project: 'YOUR_PROJECT_NAME' + platform: 'CURRENT_PLATFORM' // Optional + } + + const safe4337Pack = await Safe4337Pack.init({ + // ... + onchainAnalytics + }) + + // Execute the transaction + ``` + + + + {/* */} + + ### Get the on-chain identifier + + To get the current safe on-chain identifier, you can use the `getOnchainIdentifier` method from an initialized instance of the Protocol Kit. + + {/* */} + + ```typescript + const onchainIdentifier = protocolKit.getOnchainIdentifier() + ``` + + {/* */} + + + +## Submission Form + +
+ + diff --git a/pages/sdk/protocol-kit/guides/execute-transactions.mdx b/pages/sdk/protocol-kit/guides/execute-transactions.mdx index 4c2e9fac..5d3a9842 100644 --- a/pages/sdk/protocol-kit/guides/execute-transactions.mdx +++ b/pages/sdk/protocol-kit/guides/execute-transactions.mdx @@ -73,13 +73,16 @@ pnpm add @safe-global/api-kit \ To handle transactions and signatures, you need to create an instance of the Protocol Kit with the `provider`, `signer` and `safeAddress`. + Optionally, you can [track your Safe transactions on-chain](../../onchain-tracking.mdx) by using the `onchainAnalytics` property. + {/* */} ```typescript const protocolKitOwner1 = await Safe.init({ provider: RPC_URL, signer: OWNER_1_PRIVATE_KEY, - safeAddress: SAFE_ADDRESS + safeAddress: SAFE_ADDRESS, + onchainAnalytics // Optional }) ``` @@ -87,10 +90,10 @@ pnpm add @safe-global/api-kit \ ### Create a transaction - {/* */} - Create a `safeTransactionData` object with the properties of the transaction, add it to an array of transactions you want to execute, and pass it to the `createTransaction` method. + {/* */} + ```typescript const safeTransactionData: MetaTransactionData = { to: '0x', @@ -108,38 +111,6 @@ pnpm add @safe-global/api-kit \ For more details on what to include in a transaction, see the [`createTransaction`](../reference/safe.mdx#createtransaction) method in the reference. - ### Track the Safe transaction - - Optionally, you can track all your Safe transactions on-chain by attaching an on-chain identifier to the `data` property. - - This identifier must be unique for every project and has a length of 16 bytes. You can create a random one or derive it from a text string, maybe from your project name: - - {/* */} - - ```typescript - const onchainIdentifier = toHex( - 'TEXT_TO_DERIVE_THE_IDENTIFIER', // It could be your project name - { size: 16 } - ) - ``` - - {/* */} - - Once generated, fill out the [Ecosystem On-chain Tracking Form](https://docs.google.com/forms/d/e/1FAIpQLSfHWSPbSQwmo0mbtuFFewfLvDEOvTxfuvEl7AHOyrFE_dqpwQ/viewform) and provide the value of your `onchainIdentifier`. - - Add the `onchainIdentifier` at the end of the Safe transaction `data`. - - {/* */} - - ```typescript - safeTransaction.data.data = concat([ - safeOperation.data.data as `0x{string}`, - onchainIdentifier - ]).toString() - ``` - - {/* */} - ### Propose the transaction Before a transaction can be executed, the signer who creates it needs to send it to the Safe Transaction Service so that it is accessible by the other owners, who can then give their approval and sign the transaction. diff --git a/pages/sdk/protocol-kit/guides/multichain-safe-deployment.mdx b/pages/sdk/protocol-kit/guides/multichain-safe-deployment.mdx index 364fbba2..af488de4 100644 --- a/pages/sdk/protocol-kit/guides/multichain-safe-deployment.mdx +++ b/pages/sdk/protocol-kit/guides/multichain-safe-deployment.mdx @@ -66,12 +66,12 @@ pnpm add @safe-global/protocol-kit viem const safeAccountConfig: SafeAccountConfig = { owners: ['0x...', '0x...', '0x...'], threshold: 2 - // More optional properties + // ... } const predictedSafe: PredictedSafeProps = { safeAccountConfig - // More optional properties + // ... } ``` @@ -87,18 +87,24 @@ pnpm add @safe-global/protocol-kit viem const protocolKitSepolia = await Safe.init({ provider: sepolia.rpcUrls.default.http[0], signer: SIGNER_PRIVATE_KEY, - predictedSafe + predictedSafe, + onchainAnalytics // Optional + // ... }) const protocolKitChiado = await Safe.init({ provider: gnosisChiado.rpcUrls.default.http[0], signer: PRIVATE_KEY, - predictedSafe + predictedSafe, + onchainAnalytics // Optional + // ... }) ``` {/* */} + Optionally, you can [track your Safe deployments and transactions on-chain](../../onchain-tracking.mdx) by using the `onchainAnalytics` property. + ### Predict the Safe addresses You can predict the Safe addresses by calling the [`getAddress`](../../../reference-sdk-protocol-kit/safe-info/getaddress.mdx) method from each Protocol Kit instance and ensure that the result addresses are the same. diff --git a/pages/sdk/protocol-kit/guides/safe-deployment.mdx b/pages/sdk/protocol-kit/guides/safe-deployment.mdx index a771dc51..83c4bb95 100644 --- a/pages/sdk/protocol-kit/guides/safe-deployment.mdx +++ b/pages/sdk/protocol-kit/guides/safe-deployment.mdx @@ -59,6 +59,8 @@ pnpm add @safe-global/protocol-kit viem Initialize an instance of the Protocol Kit for each network where you want to deploy a new Safe smart account by calling the [`init`](../../../reference-sdk-protocol-kit/initialization/init.mdx) method. Pass the `provider` with its corresponding value depending on the network, the `signer` executing the deployment, and the [`predictedSafe`](../../../reference-sdk-protocol-kit/initialization/init.mdx#predictedsafe-optional) with the Safe account configuration. + Optionally, you can [track your Safe deployments and transactions on-chain](../../onchain-tracking.mdx) by using the `onchainAnalytics` property. + {/* */} ```typescript @@ -76,7 +78,8 @@ pnpm add @safe-global/protocol-kit viem const protocolKit = await Safe.init({ provider: sepolia.rpcUrls.default.http[0], signer: SIGNER_PRIVATE_KEY, - predictedSafe + predictedSafe, + onchainAnalytics // Optional }) ``` diff --git a/pages/sdk/relay-kit/guides/4337-safe-sdk.mdx b/pages/sdk/relay-kit/guides/4337-safe-sdk.mdx index a8776902..c9c6b98d 100644 --- a/pages/sdk/relay-kit/guides/4337-safe-sdk.mdx +++ b/pages/sdk/relay-kit/guides/4337-safe-sdk.mdx @@ -67,6 +67,8 @@ yarn add @safe-global/relay-kit When deploying a new Safe account, we need to pass the configuration of the Safe in the `options` property. In this case, we are configuring a Safe account that will have our signer as the only owner. + Optionally, you can [track your ERC-4337 Safe transactions on-chain](../../onchain-tracking.mdx) by using the `onchainAnalytics` property. + ```typescript const safe4337Pack = await Safe4337Pack.init({ provider: RPC_URL, @@ -76,12 +78,15 @@ yarn add @safe-global/relay-kit owners: [SIGNER_ADDRESS], threshold: 1 }, + onchainAnalytics // Optional // ... }) ``` When connecting an existing Safe account, we need to pass the `safeAddress` in the `options` property. + + Optionally, you can [track your ERC-4337 Safe transactions on-chain](../../onchain-tracking.mdx) by using the `onchainAnalytics` property. ```typescript const safe4337Pack = await Safe4337Pack.init({ @@ -91,6 +96,7 @@ yarn add @safe-global/relay-kit options: { safeAddress: '0x...' }, + onchainAnalytics // Optional // ... }) ``` @@ -166,44 +172,6 @@ yarn add @safe-global/relay-kit The `safeOperation` object has the `data` and `signatures` properties, which contain all the information about the transaction batch and the signatures of the Safe owners, respectively. - ### Track the user operation - - Optionally, you can track all your ERC-4337 Safe transactions on-chain by attaching an on-chain identifier to the user operation `callData`. - - This identifier must be unique for every project and has a length of 16 bytes. You can create a random one or derive it from a text string, maybe from your project name: - - {/* */} - - ```typescript - const onchainIdentifier = toHex( - 'TEXT_TO_DERIVE_THE_IDENTIFIER', // It could be your project name - { size: 16 } - ) - ``` - - {/* */} - - Once generated, fill the [Ecosystem On-chain Tracking Form](https://docs.google.com/forms/d/e/1FAIpQLSfHWSPbSQwmo0mbtuFFewfLvDEOvTxfuvEl7AHOyrFE_dqpwQ/viewform) and provide the value of your `onchainIdentifier`. - - Add the `onchainIdentifier` at the end of the ERC-4337 user operation `callData`. - - {/* */} - - ```typescript - safeOperation.data.callData = concat([ - safeOperation.data.callData as `0x{string}`, - onchainIdentifier - ]).toString() - - const identifiedSafeOperation = await safe4337Pack.getEstimateFee({ - safeOperation - }) - ``` - - {/* */} - - Once added, the Safe owners can sign the `identifiedSafeOperation`. - ### Sign the user operation Before sending the user operation to the bundler, it's required to sign the `safeOperation` object with the connected signer. The `signSafeOperation()` method, which receives a `SafeOperation` object, generates a signature that will be checked when the `Safe4337Module` validates the user operation.