From 6d20a81b8d33921762aef1f45ea404d32a1f07cf Mon Sep 17 00:00:00 2001 From: defispartan Date: Mon, 24 Feb 2025 23:31:42 -0600 Subject: [PATCH 1/4] feat: Lens V3 SDK version --- packages/debugger/package.json | 2 +- packages/frames.js/package.json | 6 +- packages/render/package.json | 4 +- yarn.lock | 144 ++++++++++++++++++++++++++++++++ 4 files changed, 150 insertions(+), 6 deletions(-) diff --git a/packages/debugger/package.json b/packages/debugger/package.json index 08b2d893..d279d04c 100644 --- a/packages/debugger/package.json +++ b/packages/debugger/package.json @@ -15,7 +15,7 @@ "dependencies": { "@farcaster/auth-kit": "^0.6.0", "@upstash/redis": "^1.34.3", - "@lens-protocol/client": "^2.3.2", + "@lens-protocol/client": "^0.0.0-canary-20250224081220", "@farcaster/frame-sdk": "^0.0.26", "@xmtp/xmtp-js": "^12.0.0", "is-port-reachable": "^4.0.0", diff --git a/packages/frames.js/package.json b/packages/frames.js/package.json index 7699c78a..f8a760cc 100644 --- a/packages/frames.js/package.json +++ b/packages/frames.js/package.json @@ -401,7 +401,7 @@ ], "devDependencies": { "@cloudflare/workers-types": "^4.20240320.1", - "@lens-protocol/client": "^2.3.2", + "@lens-protocol/client": "^0.0.0-canary-20250224081220", "@open-frames/types": "^0.0.6", "@remix-run/node": "^2.8.1", "@types/express": "^4.17.21", @@ -418,7 +418,7 @@ "license": "MIT", "peerDependencies": { "@cloudflare/workers-types": "^4.20240320.1", - "@lens-protocol/client": "^2.0.0", + "@lens-protocol/client": "^0.0.0-canary-20250224081220", "@types/express": "^4.17.21", "@xmtp/frames-validator": "^0.6.2", "next": "^14.1.0", @@ -437,4 +437,4 @@ "viem": "^2.7.8", "zod": "^3.24.1" } -} \ No newline at end of file +} diff --git a/packages/render/package.json b/packages/render/package.json index 930fd065..26cc2834 100644 --- a/packages/render/package.json +++ b/packages/render/package.json @@ -334,7 +334,7 @@ ], "devDependencies": { "@farcaster/frame-host-react-native": "^0.0.19", - "@lens-protocol/client": "^2.3.2", + "@lens-protocol/client": "^0.0.0-canary-20250224081220", "@rainbow-me/rainbowkit": "^2.1.2", "@remix-run/node": "^2.8.1", "@types/react-native": "^0.73.0", @@ -350,7 +350,7 @@ "license": "MIT", "peerDependencies": { "@farcaster/frame-host-react-native": "^0.0.19", - "@lens-protocol/client": "^2.0.0", + "@lens-protocol/client": "^0.0.0-canary-20250224081220", "@rainbow-me/rainbowkit": "^2.1.2", "@types/react": "^18.2.0", "@types/react-native": "^0.73.0", diff --git a/yarn.lock b/yarn.lock index 0ca28cef..effee242 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,19 @@ # yarn lockfile v1 +"@0no-co/graphql.web@^1.0.5": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@0no-co/graphql.web/-/graphql.web-1.1.1.tgz#6670b0897ee222e10f46c3b45fe5b43b90504fcd" + integrity sha512-F2i3xdycesw78QCOBHmpTn7eaD2iNXGwB2gkfwxcOfBbeauYpr8RBSyJOkDrFtKtVRMclg8Sg3n1ip0ACyUuag== + +"@0no-co/graphqlsp@^1.12.13": + version "1.12.16" + resolved "https://registry.yarnpkg.com/@0no-co/graphqlsp/-/graphqlsp-1.12.16.tgz#58fe7bad53b3ad9fdf2d5f41ddeb9b418d289a03" + integrity sha512-B5pyYVH93Etv7xjT6IfB7QtMBdaaC07yjbhN6v8H7KgFStMkPvi+oWYBTibMFRMY89qwc9H8YixXg8SXDVgYWw== + dependencies: + "@gql.tada/internal" "^1.0.0" + graphql "^15.5.0 || ^16.0.0 || ^17.0.0" + "@aashutoshrathi/word-wrap@^1.2.3": version "1.2.6" resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" @@ -2503,6 +2516,22 @@ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.1.tgz#16308cea045f0fc777b6ff20a9f25474dd8293d2" integrity sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q== +"@gql.tada/cli-utils@1.6.3": + version "1.6.3" + resolved "https://registry.yarnpkg.com/@gql.tada/cli-utils/-/cli-utils-1.6.3.tgz#b893cec74908da4df0602691e2e0b1497fda8cda" + integrity sha512-jFFSY8OxYeBxdKi58UzeMXG1tdm4FVjXa8WHIi66Gzu9JWtCE6mqom3a8xkmSw+mVaybFW5EN2WXf1WztJVNyQ== + dependencies: + "@0no-co/graphqlsp" "^1.12.13" + "@gql.tada/internal" "1.0.8" + graphql "^15.5.0 || ^16.0.0 || ^17.0.0" + +"@gql.tada/internal@1.0.8", "@gql.tada/internal@^1.0.0": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@gql.tada/internal/-/internal-1.0.8.tgz#3ba9fa6534809788bbbe103492f70b8e9d754027" + integrity sha512-XYdxJhtHC5WtZfdDqtKjcQ4d7R1s0d1rnlSs3OcBEUbYiPoJJfZU7tWsVXuv047Z6msvmr4ompJ7eLSK5Km57g== + dependencies: + "@0no-co/graphql.web" "^1.0.5" + "@graphql-typed-document-node/core@^3.2.0": version "3.2.0" resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" @@ -2868,6 +2897,20 @@ ethers "^5.7.2" tslib "^2.6.2" +"@lens-protocol/client@^0.0.0-canary-20250224081220": + version "0.0.0-canary-20250224081220" + resolved "https://registry.yarnpkg.com/@lens-protocol/client/-/client-0.0.0-canary-20250224081220.tgz#159fb3d2eddb714c86025ea89aac3d225ee2a6b2" + integrity sha512-lbmIfmBwykQ5PYe6/5UZqwZ7qbOwJmhLkvoNhS4l1sGaExMIFiOOHyhf8JXAny6Rrc+cvdoPHA38ZbaMq96lxw== + dependencies: + "@lens-protocol/env" "0.0.0-canary-20250224081220" + "@lens-protocol/graphql" "0.0.0-canary-20250224081220" + "@lens-protocol/storage" "0.0.0-canary-20250224081220" + "@lens-protocol/types" "0.0.0-canary-20250224081220" + "@urql/core" "^5.0.8" + "@urql/exchange-auth" "^2.2.0" + jwt-decode "^4.0.0" + loglevel "^1.9.2" + "@lens-protocol/client@^2.3.2": version "2.3.2" resolved "https://registry.yarnpkg.com/@lens-protocol/client/-/client-2.3.2.tgz#9421308bb691374c20a44d9784cee33d6d8a7b25" @@ -2900,6 +2943,13 @@ "@lens-protocol/shared-kernel" "0.12.0" tslib "^2.6.2" +"@lens-protocol/env@0.0.0-canary-20250224081220": + version "0.0.0-canary-20250224081220" + resolved "https://registry.yarnpkg.com/@lens-protocol/env/-/env-0.0.0-canary-20250224081220.tgz#87154b9ce6ee2360fc5f1e01fac36e14bec691f6" + integrity sha512-Cz29G28DNckgL7yroK0koow8GGW1f2g0EHkusx0FnvdhBRM1bKR1b2Nolq+ORP9grtFLOm2GsMTjIQetTQMDDg== + dependencies: + "@lens-protocol/types" "0.0.0-canary-20250224081220" + "@lens-protocol/gated-content@0.5.1": version "0.5.1" resolved "https://registry.yarnpkg.com/@lens-protocol/gated-content/-/gated-content-0.5.1.tgz#4a918d8d36ad396da3614ebde7f6e1ea5ce64b35" @@ -2915,6 +2965,16 @@ siwe "^2.1.4" tslib "^2.6.2" +"@lens-protocol/graphql@0.0.0-canary-20250224081220": + version "0.0.0-canary-20250224081220" + resolved "https://registry.yarnpkg.com/@lens-protocol/graphql/-/graphql-0.0.0-canary-20250224081220.tgz#180e7e0a8c08dcc16f161c237c59ed626280e4b9" + integrity sha512-NX7n+G3vXQwqbHqwFFbpE/Y6yYAkPWzmkEPLyorkLcM1mY7lErEf7vq+8FZXtciTbvLnm3QOWb6M5WkgCo7r0A== + dependencies: + "@lens-protocol/types" "0.0.0-canary-20250224081220" + gql.tada "^1.8.10" + graphql "^16.9.0" + type-fest "^4.26.1" + "@lens-protocol/shared-kernel@0.12.0": version "0.12.0" resolved "https://registry.yarnpkg.com/@lens-protocol/shared-kernel/-/shared-kernel-0.12.0.tgz#ea8d14ef53df3e34c7dcc8ed5e6b9002909dd65a" @@ -2926,6 +2986,14 @@ traverse "^0.6.7" tslib "^2.6.2" +"@lens-protocol/storage@0.0.0-canary-20250224081220": + version "0.0.0-canary-20250224081220" + resolved "https://registry.yarnpkg.com/@lens-protocol/storage/-/storage-0.0.0-canary-20250224081220.tgz#25f635c18f551d4b20737ad1e41ac260af9b71a2" + integrity sha512-xEQ1tfyTtC9rLq6dtums3+bkbV2g/8aKF+UQBIL8YEqE1Qkwye+fmVrKpMZGiBQJDO/nv3bpuzPA0dVlvlu3Ww== + dependencies: + "@lens-protocol/types" "0.0.0-canary-20250224081220" + zod "^3.23.8" + "@lens-protocol/storage@0.8.1": version "0.8.1" resolved "https://registry.yarnpkg.com/@lens-protocol/storage/-/storage-0.8.1.tgz#c624fb46862cb0e4a1ee8e7dfd453d48463bbd97" @@ -2935,6 +3003,14 @@ tslib "^2.6.2" zod "^3.22.4" +"@lens-protocol/types@0.0.0-canary-20250224081220": + version "0.0.0-canary-20250224081220" + resolved "https://registry.yarnpkg.com/@lens-protocol/types/-/types-0.0.0-canary-20250224081220.tgz#f2a969186fd6182fc88c5179386d5a1f509fd5d7" + integrity sha512-nvgoWYMQPfqiOLFo+cqBjRHf8BJIvoGueGsKBpxP/k47Y8APDT2vOa9ES+NXKbcK8Lq6CpyInOiS8ZiK7u0MHQ== + dependencies: + neverthrow "^8.0.0" + type-fest "^4.26.1" + "@lit-labs/ssr-dom-shim@^1.0.0", "@lit-labs/ssr-dom-shim@^1.1.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz#353ce4a76c83fadec272ea5674ede767650762fd" @@ -5021,6 +5097,11 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz#f672f6508f090fc73f08ba40ff76c20b57424778" integrity sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA== +"@rollup/rollup-linux-x64-gnu@^4.24.0": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz#5783fc0adcab7dc069692056e8ca8d83709855ce" + integrity sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA== + "@rollup/rollup-linux-x64-musl@4.13.0": version "4.13.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.0.tgz#d2f34b1b157f3e7f13925bca3288192a66755a89" @@ -6119,6 +6200,22 @@ dependencies: crypto-js "^4.2.0" +"@urql/core@^5.0.0", "@urql/core@^5.0.8": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@urql/core/-/core-5.1.0.tgz#7f4b81f1aba1ca34ae6354763abeb87ff9af84ff" + integrity sha512-yC3sw8yqjbX45GbXxfiBY8GLYCiyW/hLBbQF9l3TJrv4ro00Y0ChkKaD9I2KntRxAVm9IYBqh0awX8fwWAe/Yw== + dependencies: + "@0no-co/graphql.web" "^1.0.5" + wonka "^6.3.2" + +"@urql/exchange-auth@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@urql/exchange-auth/-/exchange-auth-2.2.0.tgz#991ebec5b3320bc0458467b466f0a749d1b3ddea" + integrity sha512-4bJR22EYa/flbhwMBj4lU8MI4cO3ddo/DX7FygWeaeHZU+RWfnQKifCKwxIYlnoV8/CgYRM4lFSMIByYlhmWcg== + dependencies: + "@urql/core" "^5.0.0" + wonka "^6.3.2" + "@vanilla-extract/babel-plugin-debug-ids@^1.0.4": version "1.0.5" resolved "https://registry.yarnpkg.com/@vanilla-extract/babel-plugin-debug-ids/-/babel-plugin-debug-ids-1.0.5.tgz#e24424f46dd7737764a4bb5ac6dcdf19240f88bc" @@ -10703,6 +10800,16 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" +gql.tada@^1.8.10: + version "1.8.10" + resolved "https://registry.yarnpkg.com/gql.tada/-/gql.tada-1.8.10.tgz#096a1b30d3c6fc74212fe07d507f01a4095f7f67" + integrity sha512-FrvSxgz838FYVPgZHGOSgbpOjhR+yq44rCzww3oOPJYi0OvBJjAgCiP6LEokZIYND2fUTXzQAyLgcvgw1yNP5A== + dependencies: + "@0no-co/graphql.web" "^1.0.5" + "@0no-co/graphqlsp" "^1.12.13" + "@gql.tada/cli-utils" "1.6.3" + "@gql.tada/internal" "1.0.8" + graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.5, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" @@ -10733,6 +10840,11 @@ graphql-tag@^2.12.6: dependencies: tslib "^2.1.0" +"graphql@^15.5.0 || ^16.0.0 || ^17.0.0", graphql@^16.9.0: + version "16.10.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.10.0.tgz#24c01ae0af6b11ea87bf55694429198aaa8e220c" + integrity sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ== + graphql@^16.8.1: version "16.8.1" resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07" @@ -12353,6 +12465,11 @@ jwt-decode@^3.1.2: resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59" integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A== +jwt-decode@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-4.0.0.tgz#2270352425fd413785b2faf11f6e755c5151bd4b" + integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA== + keccak@^3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" @@ -12642,6 +12759,11 @@ logkitty@^0.7.1: dayjs "^1.8.15" yargs "^15.1.0" +loglevel@^1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.9.2.tgz#c2e028d6c757720107df4e64508530db6621ba08" + integrity sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg== + long@^5.0.0, long@^5.2.0, long@^5.2.3: version "5.2.3" resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" @@ -14404,6 +14526,13 @@ neverthrow@^6.1.0: resolved "https://registry.yarnpkg.com/neverthrow/-/neverthrow-6.2.2.tgz#1d905abe20ef8882e4b195c7851787aa4553cf0e" integrity sha512-POR1FACqdK9jH0S2kRPzaZEvzT11wsOxLW520PQV/+vKi9dQe+hXq19EiOvYx7lSRaF5VB9lYGsPInynrnN05w== +neverthrow@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/neverthrow/-/neverthrow-8.2.0.tgz#925d988295758534d01fb7468f998680b62064f2" + integrity sha512-kOCT/1MCPAxY5iUV3wytNFUMUolzuwd/VF/1KCx7kf6CutrOsTie+84zTGTpgQycjvfLdBBdvBvFLqFD2c0wkQ== + optionalDependencies: + "@rollup/rollup-linux-x64-gnu" "^4.24.0" + next@14.1.4: version "14.1.4" resolved "https://registry.yarnpkg.com/next/-/next-14.1.4.tgz#203310f7310578563fd5c961f0db4729ce7a502d" @@ -17925,6 +18054,11 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +type-fest@^4.26.1: + version "4.35.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.35.0.tgz#007ed74d65c2ca0fb3b564b3dc8170d5c872d665" + integrity sha512-2/AwEFQDFEy30iOLjrvHDIH7e4HEWH+f1Yl1bI5XMqzuoCUqwYCdxachgsgv0og/JdVZUhbfjcJAoHj5L1753A== + type-fest@^4.28.1: version "4.28.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.28.1.tgz#5ae370169c829303012d4e2e1f568b427c1f37f7" @@ -18899,6 +19033,11 @@ why-is-node-running@^2.2.2: siginfo "^2.0.0" stackback "0.0.2" +wonka@^6.3.2: + version "6.3.4" + resolved "https://registry.yarnpkg.com/wonka/-/wonka-6.3.4.tgz#76eb9316e3d67d7febf4945202b5bdb2db534594" + integrity sha512-CjpbqNtBGNAeyNS/9W6q3kSkKE52+FjIj7AkFlLr11s/VWGUu6a2CdYSdGxocIhIVjaW/zchesBQUKPVU69Cqg== + workerd@1.20240320.1: version "1.20240320.1" resolved "https://registry.yarnpkg.com/workerd/-/workerd-1.20240320.1.tgz#f959a4805bf3bdbdf86d123482132fa30a3f34c9" @@ -19173,6 +19312,11 @@ zod@^3.20.6, zod@^3.22.4: resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== +zod@^3.23.8: + version "3.24.2" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.2.tgz#8efa74126287c675e92f46871cfc8d15c34372b3" + integrity sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ== + zod@^3.24.1: version "3.24.1" resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.1.tgz#27445c912738c8ad1e9de1bea0359fa44d9d35ee" From a05060d8559f6702eda3b39267150b30d3fbd5a9 Mon Sep 17 00:00:00 2001 From: defispartan Date: Mon, 24 Feb 2025 23:32:39 -0600 Subject: [PATCH 2/4] feat: frames.js package Lens V3 frame updates --- packages/frames.js/src/lens/index.ts | 73 ++++++++++++------------ packages/frames.js/src/lens/lens.test.ts | 15 ++--- 2 files changed, 45 insertions(+), 43 deletions(-) diff --git a/packages/frames.js/src/lens/index.ts b/packages/frames.js/src/lens/index.ts index b2f2879f..647811b7 100644 --- a/packages/frames.js/src/lens/index.ts +++ b/packages/frames.js/src/lens/index.ts @@ -1,9 +1,11 @@ import { - FrameVerifySignatureResult, - LensClient, - development, - production, + PublicClient, + testnet, + FrameVerifySignatureResult } from "@lens-protocol/client"; +import { + verifyFrameSignature, createFrameTypedData +} from "@lens-protocol/client/actions"; import type { MessageWithWalletAddressImplementation } from "../middleware/walletAddressMiddleware"; import { InvalidFrameActionPayloadError } from "../core/errors"; import type { OpenFramesActionData } from "../types"; @@ -12,15 +14,16 @@ export type LensFrameRequest = { clientProtocol: string; untrustedData: { specVersion: string; - profileId: string; - pubId: string; + account: string; + post: string; + app: string; url: string; buttonIndex: number; unixTimestamp: number; deadline: number; inputText: string; state: string; - actionResponse: string; + transactionId: string; identityToken: string; }; trustedData: { @@ -31,11 +34,12 @@ export type LensFrameRequest = { type LensFrameVerifiedFields = { url: string; buttonIndex: number; - profileId: string; - pubId: string; + account: string; + post: string; + app: string; inputText: string; state: string; - actionResponse: string; + transactionId: string; deadline: number; specVersion: string; }; @@ -66,11 +70,11 @@ export async function getLensFrameMessage( frameActionPayload: LensFrameRequest, options?: LensFrameOptions ): Promise { - const lensClientEnvironment = - options?.environment === "development" ? development : production; + //const lensClientEnvironment = + // options?.environment === "development" ? development : production; - const lensClient = new LensClient({ - environment: lensClientEnvironment, + const lensClient = PublicClient.create({ + environment: testnet, }); const { @@ -78,26 +82,27 @@ export async function getLensFrameMessage( inputText, state, buttonIndex, - actionResponse, - profileId, - pubId, + transactionId, + account, + post, + app, specVersion, deadline, identityToken, } = frameActionPayload.untrustedData; - const typedData = await lensClient.frames - .createFrameTypedData({ - url, - inputText, - state, - buttonIndex, - actionResponse, - profileId, - pubId, - specVersion, - deadline, - }) + const typedData = await createFrameTypedData(lensClient, { + url, + inputText, + state, + buttonIndex, + transactionId, + account, + post, + app, + specVersion, + deadline, + }) .catch((e) => { // eslint-disable-next-line no-console -- provide feedback to the developer console.error(e); @@ -106,7 +111,7 @@ export async function getLensFrameMessage( ); }); - const response = await lensClient.frames.verifyFrameSignature({ + const response = await verifyFrameSignature(lensClient, { identityToken, signature: frameActionPayload.trustedData.messageBytes, signedTypedData: typedData, @@ -115,12 +120,8 @@ export async function getLensFrameMessage( return { ...typedData.value, isValid: response === FrameVerifySignatureResult.Verified, - async walletAddress() { - const profile = await lensClient.profile.fetch({ - forProfileId: typedData.value.profileId, - }); - - return profile?.ownedBy.address; + walletAddress() { + return Promise.resolve(typedData.value.account); }, }; } diff --git a/packages/frames.js/src/lens/lens.test.ts b/packages/frames.js/src/lens/lens.test.ts index eaecf362..3827f724 100644 --- a/packages/frames.js/src/lens/lens.test.ts +++ b/packages/frames.js/src/lens/lens.test.ts @@ -16,11 +16,12 @@ describe("getLensMessage", () => { specVersion: "1.0.0", url: "http://localhost:3000/examples/multi-protocol", buttonIndex: 1, - profileId: "0x01df7e", - pubId: "0x01-0x01", + account: "0x0000000000000000000000000000000000000000", + post: "0x01-0x01", + app: "0x0000000000000000000000000000000000000000", inputText: "", state: '{"pageIndex":0}', - actionResponse: "", + transactionId: "", deadline: Math.round((Date.now() + 5000) / 1000), identityToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjB4MDFkZjdlIiwiZXZtQWRkcmVzcyI6IjB4OGQyNTY4NzgyOUQ2Yjg1ZDllMDAyMEI4Yzg5ZTNDYTI0ZEUyMGE4OSIsInJvbGUiOiJwcm9maWxlX2lkZW50aXR5IiwiYXV0aG9yaXphdGlvbklkIjoiZTI1M2JiZjUtZDNiOS00ZmVmLWExZjAtMmRkYjgzNGExNzAzIiwiaWF0IjoxNzIxNzQ1NDQ2LCJleHAiOjE3MjE3NDcyNDZ9.tIt8_O1SMP9MThQ9KnihhackfR1zIgoZr8RddU0aF2w", @@ -32,11 +33,11 @@ describe("getLensMessage", () => { }, }) ).resolves.toMatchObject({ - actionResponse: "", + transactionId: "", buttonIndex: 1, inputText: "", - profileId: "0x01df7e", - pubId: "0x01-0x01", + account: "0x01df7e", + post: "0x01-0x01", isValid: false, url: "http://localhost:3000/examples/multi-protocol", }); @@ -44,7 +45,7 @@ describe("getLensMessage", () => { it("throws an error if the message cannot be decoded", async () => { // eslint-disable-next-line @typescript-eslint/no-empty-function -- we don't care - consoleErrorSpy.mockImplementation(() => {}); + consoleErrorSpy.mockImplementation(() => { }); const farcasterMessage: FrameActionPayload = { untrustedData: { fid: 1689, From b2674c42dd9253ab679c5db41a236f615cb2e255 Mon Sep 17 00:00:00 2001 From: defispartan Date: Mon, 24 Feb 2025 23:32:53 -0600 Subject: [PATCH 3/4] feat: Lens V3 frame docs --- .../reference/js/lens/getLensFrameMessage.mdx | 9 +++++---- docs/pages/reference/js/lens/index.mdx | 17 +++++++---------- docs/pages/reference/render/identity/lens.mdx | 8 ++++---- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/docs/pages/reference/js/lens/getLensFrameMessage.mdx b/docs/pages/reference/js/lens/getLensFrameMessage.mdx index 527fc02b..82e35d51 100644 --- a/docs/pages/reference/js/lens/getLensFrameMessage.mdx +++ b/docs/pages/reference/js/lens/getLensFrameMessage.mdx @@ -5,7 +5,7 @@ Returns a `LensFrameMessageReturnType` object from the message payload. Throws a ## Usage ```ts -yarn add @lens-protocol/client@2.0.0 +yarn add @lens-protocol/client@canary ``` ```ts @@ -15,15 +15,16 @@ const frameMessage = await getLensFrameMessage(frameActionPayload); console.log(frameMessage); /** { - profileId: "0x01"; - pubId: "0x02-0x01"; + account: "0x0000000000000000000000000000000000000000"; + post: "0x02-0x01"; + app: "0x0000000000000000000000000000000000000000", url: "https://example.com; buttonIndex: 1; unixTimestamp: 123456789; deadline: 123456789; inputText: ""; state: ""; - actionResponse: ""; + transactionId: ""; specVersion: "1.0.0"; isValid: true, } diff --git a/docs/pages/reference/js/lens/index.mdx b/docs/pages/reference/js/lens/index.mdx index 4a8e42ca..5e86f94e 100644 --- a/docs/pages/reference/js/lens/index.mdx +++ b/docs/pages/reference/js/lens/index.mdx @@ -2,7 +2,7 @@ import { Callout, HomePage } from "vocs/components"; # Lens Support -Cross-protocol frames are supported by frames.js via familiar APIs. This guide will showcase how to write a simple stateless frame, which returns the Lens profileof the user that interacted with the frame in an OpenFrame supported application. +Cross-protocol frames are supported by frames.js via familiar APIs. This guide will showcase how to write a simple stateless frame, which returns the Lens account the user that interacted with the frame in an OpenFrame supported application. This tutorial is out of date and uses a deprecated version of frames.js. Please check the [Lens Support guide](/guides/lens) for the latest version. @@ -13,7 +13,7 @@ Cross-protocol frames are supported by frames.js via familiar APIs. This guide w First, you need to install `frames.js` and `@lens-protocol/client`. You can do this by running the following command: @@ -75,7 +75,7 @@ const acceptedProtocols: ClientProtocolId[] = [ { // [!code focus] id: "lens", // [!code focus] - version: "1.0.0", // [!code focus] + version: "1.1.0", // [!code focus] }, // [!code focus] { // [!code focus] @@ -133,7 +133,6 @@ const previousFrame = getPreviousFrame(searchParams); let fid: number | undefined; let walletAddress: string | undefined; -let lensProfileId: string | undefined; if ( // [!code focus] @@ -169,14 +168,13 @@ Now we can use data from the different message contexts to populate our `fid` an let fid: number | undefined; let walletAddress: string | undefined; -let lensProfileId: string | undefined; if ( previousFrame.postBody && isLensFrameActionPayload(previousFrame.postBody) ) { const frameMessage = await getLensFrameMessage(previousFrame.postBody); - lensProfileId = frameMessage?.profileId; // [!code focus] + walletAddress = frameMessage?.account; // [!code focus] } else if ( previousFrame.postBody && isXmtpFrameActionPayload(previousFrame.postBody) @@ -198,11 +196,11 @@ if ( // ... ``` -Here we use the `frameMessage` to extract the `verifiedProfileId`, `verifiedWalletAddress` and `requesterFid` from the Lens, XMTP, and Farcaster frame messages respectively. We then use these to populate our `lensProfileId`, `walletAddress` and `fid` variables. You can use this information to execute some action like a database query or an onchain transaction. +Here we use the `frameMessage` to extract the `verifiedWalletAddress` and `requesterFid` from the Lens, XMTP, and Farcaster frame messages respectively. We then use these to populate our `walletAddress` and `fid` variables. You can use this information to execute some action like a database query or an onchain transaction. ### Returning a Frame -Now that we have our `lensProfileId`, `fid` and `walletAddress` variables populated, we can use them to determine the next frame to return. +Now that we have our `fid` and `walletAddress` variables populated, we can use them to determine the next frame to return. ```tsx filename="example7.tsx" // ... @@ -221,7 +219,6 @@ return ( This frame gets the interactor's wallet address or FID depending on the client protocol. - {lensProfileId &&
Lens Profile ID: {lensProfileId}
} {fid &&
FID: {fid}
} {walletAddress &&
Wallet Address: {walletAddress}
} @@ -231,4 +228,4 @@ return ( ); ``` -Above, we conditionally render the `lensProfileId`, `fid` and `walletAddress` variables in the frame. +Above, we conditionally render the `fid` and `walletAddress` variables in the frame. diff --git a/docs/pages/reference/render/identity/lens.mdx b/docs/pages/reference/render/identity/lens.mdx index d3e4bbed..fefb8224 100644 --- a/docs/pages/reference/render/identity/lens.mdx +++ b/docs/pages/reference/render/identity/lens.mdx @@ -9,15 +9,15 @@ In order to use Lens identity you need to install `@rainbow-me/rainbowkit`, `@le :::code-group ```bash [npm] -npm install @rainbow-me/rainbowkit @lens-protocol/client viem wagmi +npm install @rainbow-me/rainbowkit @lens-protocol/client@canary viem wagmi ``` ```bash [yarn] -yarn add @rainbow-me/rainbowkit @lens-protocol/client viem wagmi +yarn add @rainbow-me/rainbowkit @lens-protocol/client@canary viem wagmi ``` ```bash [pnpm] -pnpm add @rainbow-me/rainbowkit @lens-protocol/client viem wagmi +pnpm add @rainbow-me/rainbowkit @lens-protocol/client@canary viem wagmi ``` ::: @@ -36,7 +36,7 @@ import { WebStorage } from "@frames.js/render/identity/storage"; export function MyFrame() { const lensFrameContext = useLensFrameContext({ fallbackContext: { - pubId: "0x01-0x01", + post: "0x01-0x01", }, }); const signerState = useLensIdentity({ From af5dcbfabc0e74a7bc73e19bde6cbf9f68a7aafb Mon Sep 17 00:00:00 2001 From: defispartan Date: Mon, 24 Feb 2025 23:33:15 -0600 Subject: [PATCH 4/4] feat: Lens V3 frame client (WIP) --- .../src/identity/lens/use-lens-identity.tsx | 184 +++++++++--------- 1 file changed, 88 insertions(+), 96 deletions(-) diff --git a/packages/render/src/identity/lens/use-lens-identity.tsx b/packages/render/src/identity/lens/use-lens-identity.tsx index b1806d93..dd593a30 100644 --- a/packages/render/src/identity/lens/use-lens-identity.tsx +++ b/packages/render/src/identity/lens/use-lens-identity.tsx @@ -7,7 +7,8 @@ import { useSignMessage, useSwitchChain, } from "wagmi"; -import { LensClient, development, production } from "@lens-protocol/client"; +import { PublicClient, testnet } from "@lens-protocol/client"; +import { signFrameAction, createFrameTypedData, fetchAccountManagers } from "@lens-protocol/client/actions"; import type { SignerStateActionContext, SignerStateInstance, @@ -17,33 +18,34 @@ import type { Storage } from "../types"; import { WebStorage } from "../storage"; import { useFreshRef } from "../../hooks/use-fresh-ref"; import type { LensFrameContext } from "./use-lens-context"; +import { fetchAccountsAvailable } from "@lens-protocol/client/actions"; export type LensProfile = { - id: string; - handle?: string; + account: string; + username: string; }; export type LensSigner = { - profileId: string; + account: string; accessToken: string; identityToken: string; - handle: string; - address: `0x${string}`; + username: string; }; type LensFrameRequest = { clientProtocol: string; untrustedData: { specVersion: string; - profileId: string; - pubId: string; + account: string; + post: string; + app: string; url: string; buttonIndex: number; unixTimestamp: number; deadline?: number; inputText?: string; state?: string; - actionResponse?: string; + transactionId?: string; identityToken: string; }; trustedData: { @@ -79,6 +81,9 @@ type LensIdentityOptions = { const defaultStorage = new WebStorage(); +// Testnet app address (demo) +const TESTNET_APP_ADDRESS = "0xaC19aa2402b3AC3f9Fe471D4783EC68595432465"; + export function useLensIdentity({ storage = defaultStorage, storageKey = "lensProfile", @@ -99,11 +104,10 @@ export function useLensIdentity({ const storageKeyRef = useFreshRef(storageKey); const addressRef = useFreshRef(address); - const lensClient = useRef( - new LensClient({ - environment: environment === "development" ? development : production, - }) - ).current; + const lensClient = PublicClient.create({ + environment: testnet, + storage: window.localStorage, + }); const connectRef = useFreshRef(connect); @@ -130,70 +134,50 @@ export function useLensIdentity({ async (profile: LensProfile) => { try { const walletAddress = addressRef.current; - if (!walletAddress) { throw new Error("No wallet connected"); } - setShowProfileSelector(false); - const { id, text } = await lensClient.authentication.generateChallenge({ - signedBy: walletAddress, - for: profile.id, - }); - const signature = await signMessageAsync({ - message: { - raw: - typeof text === "string" - ? Buffer.from(text) - : Buffer.from(text as Uint8Array), + const authenticated = await lensClient.login({ + accountOwner: { + account: profile.account, + app: TESTNET_APP_ADDRESS, + owner: walletAddress, + }, + signMessage: async (message: string) => { + const signature = await signMessageAsync({ + message: { raw: Buffer.from(message) }, + }); + return signature; }, }); - await lensClient.authentication.authenticate({ id, signature }); - - const accessTokenResult = - await lensClient.authentication.getAccessToken(); - const identityTokenResult = - await lensClient.authentication.getIdentityToken(); - const accessToken = accessTokenResult.unwrap(); - const identityToken = identityTokenResult.unwrap(); - const profileId = await lensClient.authentication.getProfileId(); - const profileInfo = await lensClient.profile.fetch({ - forProfileId: profileId, - }); - const handle = profileInfo?.handle?.localName - ? `${profileInfo.handle.localName}.lens` - : ""; - - if (profileId) { - const signer: LensSigner = { - accessToken, - profileId, - address: walletAddress, - identityToken, - handle, - }; - - await storageRef.current.set( - storageKeyRef.current, - () => signer - ); - - setLensSigner(signer); + if (authenticated.isErr()) { + throw new Error("Authentication failed: " + authenticated.error); } + + const sessionClient = authenticated.value; + + const signer: LensSigner = { + account: profile.account, + accessToken: sessionClient.accessToken, + identityToken: sessionClient.idToken, + username: profile.username, + }; + + await storageRef.current.set( + storageKeyRef.current, + () => signer + ); + + setLensSigner(signer); } catch (error) { // eslint-disable-next-line no-console -- provide feedback console.error("@frames.js/render: Create Lens signer failed", error); } }, - [ - addressRef, - lensClient.authentication, - lensClient.profile, - signMessageAsync, - storageKeyRef, - ] + [addressRef, lensClient, signMessageAsync, storageKeyRef] ); const onSignerlessFramePress = useCallback(async () => { @@ -212,23 +196,33 @@ export function useLensIdentity({ return; } - const managedProfiles = await lensClient.wallet.profilesManaged({ - for: currentAddress, + const managedProfiles = await fetchAccountsAvailable(lensClient, { + managedBy: currentAddress, + includeOwned: true, }); - const profiles: LensProfile[] = managedProfiles.items.map((p) => ({ - id: p.id, - handle: p.handle ? `${p.handle.localName}.lens` : undefined, - })); - - if (!profiles[0]) { - throw new Error("No Lens profiles managed by connected address"); - } + if (managedProfiles.isOk()) { + const profiles = managedProfiles.value.items.map((p) => ({ + account: p.account.address, + username: p.account.username + ? `${p.account.username}` + : p.account.address, + })); + + if (!profiles[0]) { + throw new Error("No Lens profiles managed by connected address"); + } - if (managedProfiles.items.length > 1) { - setAvailableProfiles(profiles); - setShowProfileSelector(true); + if (managedProfiles.value.items.length > 1) { + setAvailableProfiles(profiles); + setShowProfileSelector(true); + } else { + await handleSelectProfile(profiles[0]); + } } else { - await handleSelectProfile(profiles[0]); + console.error( + "@frames.js/render: Create Lens signer failed", + managedProfiles.error + ); } } catch (error) { // eslint-disable-next-line no-console -- provide feedback @@ -240,13 +234,13 @@ export function useLensIdentity({ addressRef, connectRef, handleSelectProfile, - lensClient.wallet, lensSignerRef, + lensClient, ]); const activeConnectionRef = useFreshRef(activeConnection); - const signFrameAction: SignFrameActionFunction< + const signLensFrameAction: SignFrameActionFunction< SignerStateActionContext, LensFrameRequest > = useCallback( @@ -257,23 +251,22 @@ export function useLensIdentity({ throw new Error("No lens signer active"); } - const profileManagers = await lensClient.profile.managers({ - for: signer.profileId, - }); + const profileManagers = await fetchAccountManagers(lensClient); const lensManagerEnabled = profileManagers.items.some( (manager) => manager.isLensManager ); if (lensManagerEnabled) { - const result = await lensClient.frames.signFrameAction({ + const result = await signFrameAction(lensClient, { url: actionContext.url, inputText: actionContext.inputText || "", state: actionContext.state || "", buttonIndex: actionContext.buttonIndex, - actionResponse: + transactionId: actionContext.type === "tx-post" ? actionContext.transactionId : "", - profileId: signer.profileId, - pubId: actionContext.frameContext.pubId || "", + account: signer.account, + app: TESTNET_APP_ADDRESS, + post: actionContext.frameContext.pubId || "", specVersion: "1.0.0", }); @@ -306,16 +299,17 @@ export function useLensIdentity({ }; } - const typedData = await lensClient.frames.createFrameTypedData({ + const typedData = await createFrameTypedData(lensClient, { url: actionContext.url, inputText: actionContext.inputText || "", state: actionContext.state || "", buttonIndex: actionContext.buttonIndex, - actionResponse: + transactionId: actionContext.type === "tx-post" ? actionContext.transactionId : "", - profileId: signer.profileId, - pubId: actionContext.frameContext.pubId || "", - specVersion: "1.0.0", + account: signer.account, + post: actionContext.frameContext.pubId || "", + app: TESTNET_APP_ADDRESS, + specVersion: "1.1.0", deadline: Math.floor(Date.now() / 1000) + 86400, // 1 day }); @@ -346,7 +340,7 @@ export function useLensIdentity({ return { body: { - clientProtocol: "lens@1.0.0", + clientProtocol: "lens@1.1.0", untrustedData: { ...typedData.value, identityToken: signer.identityToken, @@ -361,8 +355,6 @@ export function useLensIdentity({ }, [ activeConnectionRef, - lensClient.frames, - lensClient.profile, lensSignerRef, signTypedDataAsync, switchChainAsync, @@ -392,7 +384,7 @@ export function useLensIdentity({ get hasSigner() { return !!lensSignerRef.current?.accessToken; }, - signFrameAction, + signFrameAction: signLensFrameAction, get isLoadingSigner() { return isLoadingRef.current; },