diff --git a/.changeset/perfect-cups-suffer.md b/.changeset/perfect-cups-suffer.md new file mode 100644 index 000000000..85c9e3b4e --- /dev/null +++ b/.changeset/perfect-cups-suffer.md @@ -0,0 +1,5 @@ +--- +"@lens-protocol/client": patch +--- + +feat: added `isOpenActionModuleWithReferralFee` helper function diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7ee678b85..025a149ac 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,10 +15,10 @@ jobs: - uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v2.4.0 + uses: pnpm/action-setup@v2 - name: Use Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" cache: "pnpm" @@ -34,10 +34,10 @@ jobs: - uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v2.4.0 + uses: pnpm/action-setup@v2 - name: Use Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" cache: "pnpm" @@ -60,10 +60,10 @@ jobs: - uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v2.4.0 + uses: pnpm/action-setup@v2 - name: Use Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" cache: "pnpm" @@ -89,10 +89,10 @@ jobs: - uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v2.4.0 + uses: pnpm/action-setup@v2 - name: Use Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" cache: "pnpm" @@ -110,10 +110,10 @@ jobs: - uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v2.4.0 + uses: pnpm/action-setup@v2 - name: Use Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" cache: "pnpm" diff --git a/examples/node/scripts/publication/recipes/mirrorReferrer.ts b/examples/node/scripts/publication/recipes/mirrorReferrer.ts new file mode 100644 index 000000000..2b77f3753 --- /dev/null +++ b/examples/node/scripts/publication/recipes/mirrorReferrer.ts @@ -0,0 +1,117 @@ +import { + OpenActionModuleFragment, + PublicationType, + isMirrorPublication, + isOpenActionModuleWithReferralFee, + isRelaySuccess, +} from '@lens-protocol/client'; + +import { getAuthenticatedClient } from '../../shared/getAuthenticatedClient'; +import { setupWallet } from '../../shared/setupWallet'; + +function mapOpenActionModuleToInputType(openActionModule: OpenActionModuleFragment) { + switch (openActionModule.__typename) { + case 'SimpleCollectOpenActionSettings': + return { + simpleCollectOpenAction: true, + }; + case 'MultirecipientFeeCollectOpenActionSettings': + return { + multirecipientCollectOpenAction: true, + }; + default: + throw new Error(`Unsupported openActionModule type: ${openActionModule.__typename}`); + } +} + +async function main() { + const wallet = setupWallet(); + const client = await getAuthenticatedClient(wallet); + + // fetch mirrors + const mirrorsResult = await client.publication.fetchAll({ + where: { + publicationTypes: [PublicationType.Mirror], + }, + }); + + let mirror = undefined; + + // iterate over pages of mirrors to find a mirror of a post with referralFee + while (mirrorsResult.pageInfo.next && !mirror) { + console.log(`Fetching page for cursor: ${mirrorsResult.pageInfo.next}`); + + const nextPage = await mirrorsResult.next(); + + if (nextPage) { + // type safe as Mirror + const mirrors = mirrorsResult.items.filter(isMirrorPublication); + + // look for referralFee + mirror = mirrors.find((m) => + m.mirrorOn.openActionModules.find((o) => 'referralFee' in o && o.referralFee > 0), + ); + } + } + + if (!mirror) { + throw new Error('No mirror found with referralFee'); + } + + const openActionWithReferralFee = mirror.mirrorOn.openActionModules.find( + (o) => 'referralFee' in o && o.referralFee > 0, + ); + + // type safe as OpenActionModuleWithReferralFeeFragment + if ( + !openActionWithReferralFee || + (openActionWithReferralFee && !isOpenActionModuleWithReferralFee(openActionWithReferralFee)) + ) { + throw new Error('No openAction found with referralFee'); + } + + console.log( + `We found a mirror with ID ${mirror.id} by profile ${mirror.by.id} + of a publication ID ${mirror.mirrorOn.id} with openActionModule ${openActionWithReferralFee.__typename} and referralFee: ${openActionWithReferralFee.referralFee}`, + ); + + // map the openActionModule to the correct input type + const actOnInput = mapOpenActionModuleToInputType(openActionWithReferralFee); + + // now collect the publication + // notice that paid actions need to be signed and sent through broadcast + const resultTypedData = await client.publication.actions.createActOnTypedData({ + actOn: actOnInput, + for: mirror.mirrorOn.id, + referrers: [{ profileId: mirror.by.id }, { publicationId: mirror.id }], + }); + + const { id, typedData } = resultTypedData.unwrap(); + + console.log(`Typed data: `, typedData); + + // sign with the wallet + const signedTypedData = await wallet._signTypedData( + typedData.domain, + typedData.types, + typedData.value, + ); + + console.log(`Broadcasting signed typed data...`); + + const broadcastResult = await client.transaction.broadcastOnchain({ + id, + signature: signedTypedData, + }); + + const broadcastValue = broadcastResult.unwrap(); + + if (!isRelaySuccess(broadcastValue)) { + console.log(`Something went wrong`, broadcastValue); + return; + } + + console.log(`Transaction was successfully broadcasted with txId`, broadcastValue.txId); +} + +main(); diff --git a/packages/client/src/submodules/notifications/Notifications.ts b/packages/client/src/submodules/notifications/Notifications.ts index a6a49f600..5c6627b64 100644 --- a/packages/client/src/submodules/notifications/Notifications.ts +++ b/packages/client/src/submodules/notifications/Notifications.ts @@ -31,8 +31,7 @@ export type NotificationFragment = | MentionNotificationFragment | MirrorNotificationFragment | QuoteNotificationFragment - | ReactionNotificationFragment - | Record; + | ReactionNotificationFragment; /** * Notifications on many activities for a profile. diff --git a/packages/client/src/submodules/publication/helpers/index.ts b/packages/client/src/submodules/publication/helpers/index.ts index c5f595cf9..7ed55c3f4 100644 --- a/packages/client/src/submodules/publication/helpers/index.ts +++ b/packages/client/src/submodules/publication/helpers/index.ts @@ -1 +1,2 @@ -export * from './helpers'; +export * from './publicationTypes'; +export * from './openActions'; diff --git a/packages/client/src/submodules/publication/helpers/openActions.ts b/packages/client/src/submodules/publication/helpers/openActions.ts new file mode 100644 index 000000000..0a7b49195 --- /dev/null +++ b/packages/client/src/submodules/publication/helpers/openActions.ts @@ -0,0 +1,48 @@ +import { + LegacyAaveFeeCollectModuleSettingsFragment, + LegacyErc4626FeeCollectModuleSettingsFragment, + LegacyFeeCollectModuleSettingsFragment, + LegacyFreeCollectModuleSettingsFragment, + LegacyLimitedFeeCollectModuleSettingsFragment, + LegacyLimitedTimedFeeCollectModuleSettingsFragment, + LegacyMultirecipientFeeCollectModuleSettingsFragment, + LegacyRevertCollectModuleSettingsFragment, + LegacySimpleCollectModuleSettingsFragment, + LegacyTimedFeeCollectModuleSettingsFragment, + MultirecipientFeeCollectOpenActionSettingsFragment, + SimpleCollectOpenActionSettingsFragment, + UnknownOpenActionModuleSettingsFragment, +} from '../../../graphql/fragments.generated'; + +export type OpenActionModuleFragment = + | LegacyAaveFeeCollectModuleSettingsFragment + | LegacyErc4626FeeCollectModuleSettingsFragment + | LegacyFeeCollectModuleSettingsFragment + | LegacyFreeCollectModuleSettingsFragment + | LegacyLimitedFeeCollectModuleSettingsFragment + | LegacyLimitedTimedFeeCollectModuleSettingsFragment + | LegacyMultirecipientFeeCollectModuleSettingsFragment + | LegacyRevertCollectModuleSettingsFragment + | LegacySimpleCollectModuleSettingsFragment + | LegacyTimedFeeCollectModuleSettingsFragment + | MultirecipientFeeCollectOpenActionSettingsFragment + | SimpleCollectOpenActionSettingsFragment + | UnknownOpenActionModuleSettingsFragment; + +export type OpenActionModuleWithReferralFeeFragment = + | LegacyAaveFeeCollectModuleSettingsFragment + | LegacyErc4626FeeCollectModuleSettingsFragment + | LegacyFeeCollectModuleSettingsFragment + | LegacyLimitedFeeCollectModuleSettingsFragment + | LegacyLimitedTimedFeeCollectModuleSettingsFragment + | LegacyMultirecipientFeeCollectModuleSettingsFragment + | LegacySimpleCollectModuleSettingsFragment + | LegacyTimedFeeCollectModuleSettingsFragment + | MultirecipientFeeCollectOpenActionSettingsFragment + | SimpleCollectOpenActionSettingsFragment; + +export function isOpenActionModuleWithReferralFee( + module: OpenActionModuleFragment, +): module is OpenActionModuleWithReferralFeeFragment { + return 'referralFee' in module; +} diff --git a/packages/client/src/submodules/publication/helpers/helpers.ts b/packages/client/src/submodules/publication/helpers/publicationTypes.ts similarity index 100% rename from packages/client/src/submodules/publication/helpers/helpers.ts rename to packages/client/src/submodules/publication/helpers/publicationTypes.ts diff --git a/packages/react/src/wallet/infrastructure/SignerFactory.ts b/packages/react/src/wallet/infrastructure/SignerFactory.ts index 211e29b42..468bf026f 100644 --- a/packages/react/src/wallet/infrastructure/SignerFactory.ts +++ b/packages/react/src/wallet/infrastructure/SignerFactory.ts @@ -35,7 +35,6 @@ export class SignerFactory implements ISignerFactory { const signerAddress = await signer.getAddress(); - // TODO fix: this condition is not necessarily true during authentication with a EIP-1271 wallet if (!isTheSameAddress(address, signerAddress)) { return failure(new WalletConnectionError(WalletConnectionErrorReason.WRONG_ACCOUNT)); }