From 63fe50b469b9a8cd2769c144794751774f88bbd0 Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Tue, 31 Oct 2023 14:18:15 -0400 Subject: [PATCH 1/8] Revert "Revert "Switch to localStorage (#1782)" (#1796)" This reverts commit cc21dbfd3d197d77b8f363be64e35229e9feb4c5. --- .changeset/slow-peaches-vanish.md | 5 +++++ packages/fcl/src/fcl.js | 6 ++++-- packages/fcl/src/utils/web/default-config.js | 17 ++--------------- packages/fcl/src/utils/web/index.js | 11 ++++++----- packages/fcl/src/utils/web/storage.js | 13 +++++++++++++ 5 files changed, 30 insertions(+), 22 deletions(-) create mode 100644 .changeset/slow-peaches-vanish.md create mode 100644 packages/fcl/src/utils/web/storage.js diff --git a/.changeset/slow-peaches-vanish.md b/.changeset/slow-peaches-vanish.md new file mode 100644 index 000000000..ac02855d1 --- /dev/null +++ b/.changeset/slow-peaches-vanish.md @@ -0,0 +1,5 @@ +--- +"@onflow/fcl": minor +--- + +Use localStorage as default & export LOCAL_STORAGE/SESSION_STORAGE as helpers for fcl.storage.default configuration key diff --git a/packages/fcl/src/fcl.js b/packages/fcl/src/fcl.js index 2b3677330..a8917b826 100644 --- a/packages/fcl/src/fcl.js +++ b/packages/fcl/src/fcl.js @@ -1,10 +1,10 @@ -export * from './shared-exports'; +export * from "./shared-exports" import {getMutate} from "./exec/mutate" export const mutate = getMutate({platform: "web"}) import {getCurrentUser} from "./current-user" -const currentUser = getCurrentUser({platform:"web"}) +const currentUser = getCurrentUser({platform: "web"}) export {currentUser} @@ -19,6 +19,8 @@ export const logIn = (opts = {}) => currentUser().authenticate(opts) export const authz = currentUser().authorization +export {LOCAL_STORAGE, SESSION_STORAGE} from "./utils/web" + import {config} from "@onflow/config" import {getDefaultConfig, coreStrategies} from "./utils/web" import {initServiceRegistry} from "./current-user/exec-service/plugins" diff --git a/packages/fcl/src/utils/web/default-config.js b/packages/fcl/src/utils/web/default-config.js index 3bbf571b0..6bc0ae177 100644 --- a/packages/fcl/src/utils/web/default-config.js +++ b/packages/fcl/src/utils/web/default-config.js @@ -1,21 +1,8 @@ -const isServerSide = () => typeof window === "undefined" - -const getSessionStorage = () => { - try { - const SESSION_STORAGE = { - can: !isServerSide(), - get: async key => JSON.parse(sessionStorage.getItem(key)), - put: async (key, value) => sessionStorage.setItem(key, JSON.stringify(value)), - } - return SESSION_STORAGE - } catch (error) { - return null - } -} +import {LOCAL_STORAGE} from "./storage" export const getDefaultConfig = () => { return { "discovery.wallet.method.default": "IFRAME/RPC", - "fcl.storage.default": getSessionStorage(), + "fcl.storage.default": LOCAL_STORAGE, } } diff --git a/packages/fcl/src/utils/web/index.js b/packages/fcl/src/utils/web/index.js index edd0b8cb9..7c943c9f8 100644 --- a/packages/fcl/src/utils/web/index.js +++ b/packages/fcl/src/utils/web/index.js @@ -1,5 +1,6 @@ -export {renderFrame} from './render-frame' -export {renderPop} from './render-pop' -export {renderTab} from './render-tab' -export {getDefaultConfig} from './default-config' -export {coreStrategies} from './coreStrategies' +export {renderFrame} from "./render-frame" +export {renderPop} from "./render-pop" +export {renderTab} from "./render-tab" +export {getDefaultConfig} from "./default-config" +export {coreStrategies} from "./coreStrategies" +export {LOCAL_STORAGE, SESSION_STORAGE} from "./storage" diff --git a/packages/fcl/src/utils/web/storage.js b/packages/fcl/src/utils/web/storage.js new file mode 100644 index 000000000..3789191e4 --- /dev/null +++ b/packages/fcl/src/utils/web/storage.js @@ -0,0 +1,13 @@ +const isServerSide = () => typeof window === "undefined" + +export const SESSION_STORAGE = { + can: !isServerSide(), + get: async key => JSON.parse(sessionStorage.getItem(key)), + put: async (key, value) => sessionStorage.setItem(key, JSON.stringify(value)), +} + +export const LOCAL_STORAGE = { + can: !isServerSide(), + get: async key => JSON.parse(localStorage.getItem(key)), + put: async (key, value) => localStorage.setItem(key, JSON.stringify(value)), +} From 798de8b26e0e168201376e746fc362063d07b861 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Fri, 1 Nov 2024 12:24:43 -0700 Subject: [PATCH 2/8] switch storage to TS --- packages/fcl/src/utils/web/storage.js | 13 ------------ packages/fcl/src/utils/web/storage.ts | 29 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 13 deletions(-) delete mode 100644 packages/fcl/src/utils/web/storage.js create mode 100644 packages/fcl/src/utils/web/storage.ts diff --git a/packages/fcl/src/utils/web/storage.js b/packages/fcl/src/utils/web/storage.js deleted file mode 100644 index 3789191e4..000000000 --- a/packages/fcl/src/utils/web/storage.js +++ /dev/null @@ -1,13 +0,0 @@ -const isServerSide = () => typeof window === "undefined" - -export const SESSION_STORAGE = { - can: !isServerSide(), - get: async key => JSON.parse(sessionStorage.getItem(key)), - put: async (key, value) => sessionStorage.setItem(key, JSON.stringify(value)), -} - -export const LOCAL_STORAGE = { - can: !isServerSide(), - get: async key => JSON.parse(localStorage.getItem(key)), - put: async (key, value) => localStorage.setItem(key, JSON.stringify(value)), -} diff --git a/packages/fcl/src/utils/web/storage.ts b/packages/fcl/src/utils/web/storage.ts new file mode 100644 index 000000000..5553a0778 --- /dev/null +++ b/packages/fcl/src/utils/web/storage.ts @@ -0,0 +1,29 @@ +const isServerSide = () => typeof window === "undefined" +const safeParseJSON = (str?: string | null) => { + if (str == null) return null + try { + return JSON.parse(str) + } catch (error) { + return null + } +} + +export type StorageProvider = { + can: boolean + get: (key: string) => Promise + put: (key: string, value: any) => Promise +} + +export const SESSION_STORAGE = { + can: !isServerSide() && !!window.sessionStorage, + get: async (key: string) => safeParseJSON(sessionStorage.getItem(key)), + put: async (key: string, value: any) => + sessionStorage.setItem(key, JSON.stringify(value)), +} + +export const LOCAL_STORAGE = { + can: !isServerSide() && !!window.localStorage, + get: async (key: string) => safeParseJSON(localStorage.getItem(key)), + put: async (key: string, value: any) => + localStorage.setItem(key, JSON.stringify(value)), +} From 4c3c86b5a951260897edc44128ff35092730fa11 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Fri, 1 Nov 2024 12:41:09 -0700 Subject: [PATCH 3/8] update package-lock.json --- package-lock.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index e9f058c21..a9092608d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30061,13 +30061,13 @@ }, "packages/fcl": { "name": "@onflow/fcl", - "version": "1.12.4-alpha.3", + "version": "1.12.4-alpha.5", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.25.7", "@onflow/config": "1.5.1-alpha.0", - "@onflow/fcl-core": "1.13.0-alpha.2", - "@onflow/fcl-wc": "5.4.1-alpha.1", + "@onflow/fcl-core": "1.13.0-alpha.3", + "@onflow/fcl-wc": "5.4.1-alpha.3", "@onflow/interaction": "0.0.11", "@onflow/rlp": "1.2.3-alpha.0", "@onflow/sdk": "1.5.4-alpha.1", @@ -30131,7 +30131,7 @@ }, "packages/fcl-core": { "name": "@onflow/fcl-core", - "version": "1.13.0-alpha.2", + "version": "1.13.0-alpha.3", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.25.7", @@ -30180,12 +30180,12 @@ }, "packages/fcl-react-native": { "name": "@onflow/fcl-react-native", - "version": "1.9.7-alpha.2", + "version": "1.9.7-alpha.3", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.25.7", "@onflow/config": "1.5.1-alpha.0", - "@onflow/fcl-core": "1.13.0-alpha.2", + "@onflow/fcl-core": "1.13.0-alpha.3", "@onflow/interaction": "0.0.11", "@onflow/rlp": "1.2.3-alpha.0", "@onflow/sdk": "1.5.4-alpha.1", @@ -30233,7 +30233,7 @@ }, "packages/fcl-wc": { "name": "@onflow/fcl-wc", - "version": "5.4.1-alpha.1", + "version": "5.4.1-alpha.3", "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.25.7", @@ -30253,7 +30253,7 @@ "jest": "^29.7.0" }, "peerDependencies": { - "@onflow/fcl-core": "1.13.0-alpha.2" + "@onflow/fcl-core": "1.13.0-alpha.3" } }, "packages/fcl/node_modules/typescript": { From ad0c3e525649dec2b0d75b09c1a69f6a24ad0a36 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Fri, 1 Nov 2024 13:37:55 -0700 Subject: [PATCH 4/8] prettier --- packages/fcl/src/fcl.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/fcl/src/fcl.ts b/packages/fcl/src/fcl.ts index 7650fc7b8..0d859d0e4 100644 --- a/packages/fcl/src/fcl.ts +++ b/packages/fcl/src/fcl.ts @@ -99,5 +99,4 @@ initServiceRegistry({coreStrategies}) // Based on the user's config initFclWcLoader() - -export {LOCAL_STORAGE, SESSION_STORAGE} from "./utils/web" \ No newline at end of file +export {LOCAL_STORAGE, SESSION_STORAGE} from "./utils/web" From d22bc5a5f6c02ac1fcd07ee46b8bbf5126d7ce88 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Wed, 13 Nov 2024 08:12:41 -0800 Subject: [PATCH 5/8] Update configuration --- packages/fcl-core/src/current-user/index.js | 315 ++++++++++--------- packages/fcl-core/src/fcl-core.ts | 2 + packages/fcl-core/src/utils/storage.ts | 5 + packages/fcl/src/fcl.ts | 14 +- packages/fcl/src/utils/web/default-config.js | 3 - packages/fcl/src/utils/web/storage.ts | 12 +- 6 files changed, 182 insertions(+), 169 deletions(-) create mode 100644 packages/fcl-core/src/utils/storage.ts diff --git a/packages/fcl-core/src/current-user/index.js b/packages/fcl-core/src/current-user/index.js index b1a87c33b..ad0ca5a2b 100644 --- a/packages/fcl-core/src/current-user/index.js +++ b/packages/fcl-core/src/current-user/index.js @@ -1,6 +1,6 @@ import "../default-config" import * as t from "@onflow/types" -import {account, arg} from "@onflow/sdk" +import {arg} from "@onflow/sdk" import {config} from "@onflow/config" import {spawn, send, INIT, SUBSCRIBE, UNSUBSCRIBE} from "@onflow/util-actor" import {withPrefix, sansPrefix} from "@onflow/util-address" @@ -46,53 +46,62 @@ const getStoredUser = async storage => { return stored || fallback } -const HANDLERS = { - [INIT]: async ctx => { - if (typeof window === "undefined") { - console.warn( - ` +const makeHandlers = cfg => { + // Wrapper for backwards compatibility + const getStorageProvider = async () => { + if (cfg.getStorageProvider) return await cfg.getStorageProvider() + return await config.first(["fcl.storage", "fcl.storage.default"]) + } + + return { + [INIT]: async ctx => { + if (typeof window === "undefined") { + console.warn( + ` %cFCL Warning ============================ "currentUser" is only available in the browser. For more info, please see the docs: https://docs.onflow.org/fcl/ ============================ `, - "font-weight:bold;font-family:monospace;" - ) - } + "font-weight:bold;font-family:monospace;" + ) + } - ctx.merge(JSON.parse(DATA)) - const storage = await config.first(["fcl.storage", "fcl.storage.default"]) - if (storage.can) { - const user = await getStoredUser(storage) - if (notExpired(user)) ctx.merge(user) - } - }, - [SUBSCRIBE]: (ctx, letter) => { - ctx.subscribe(letter.from) - ctx.send(letter.from, UPDATED, {...ctx.all()}) - }, - [UNSUBSCRIBE]: (ctx, letter) => { - ctx.unsubscribe(letter.from) - }, - [SNAPSHOT]: async (ctx, letter) => { - letter.reply({...ctx.all()}) - }, - [SET_CURRENT_USER]: async (ctx, letter, data) => { - ctx.merge(data) - const storage = await config.first(["fcl.storage", "fcl.storage.default"]) - if (storage.can) storage.put(NAME, ctx.all()) - ctx.broadcast(UPDATED, {...ctx.all()}) - }, - [DEL_CURRENT_USER]: async (ctx, letter) => { - ctx.merge(JSON.parse(DATA)) - const storage = await config.first(["fcl.storage", "fcl.storage.default"]) - if (storage.can) storage.put(NAME, ctx.all()) - ctx.broadcast(UPDATED, {...ctx.all()}) - }, + ctx.merge(JSON.parse(DATA)) + console.log("Storage Provider", await getStorageProvider()) + const storage = await getStorageProvider() + if (storage.can) { + const user = await getStoredUser(storage) + if (notExpired(user)) ctx.merge(user) + } + }, + [SUBSCRIBE]: (ctx, letter) => { + ctx.subscribe(letter.from) + ctx.send(letter.from, UPDATED, {...ctx.all()}) + }, + [UNSUBSCRIBE]: (ctx, letter) => { + ctx.unsubscribe(letter.from) + }, + [SNAPSHOT]: async (ctx, letter) => { + letter.reply({...ctx.all()}) + }, + [SET_CURRENT_USER]: async (ctx, letter, data) => { + ctx.merge(data) + const storage = await getStorageProvider() + if (storage.can) storage.put(NAME, ctx.all()) + ctx.broadcast(UPDATED, {...ctx.all()}) + }, + [DEL_CURRENT_USER]: async (ctx, letter) => { + ctx.merge(JSON.parse(DATA)) + const storage = await getStorageProvider() + if (storage.can) storage.put(NAME, ctx.all()) + ctx.broadcast(UPDATED, {...ctx.all()}) + }, + } } -const spawnCurrentUser = () => spawn(HANDLERS, NAME) +const spawnCurrentUser = cfg => spawn(makeHandlers(cfg), NAME) function notExpired(user) { return ( @@ -148,18 +157,14 @@ const makeConfig = async ({ /** * @description - Factory function to get the authenticate method - * @param {object} [opts] - Options - * @param {object} [opts.platform] - platform that runs the function - * @param {object} [opts.service] - Optional service to use for authentication - * @param {object} [opts.discovery] - Optional discovery options + * @param {CurrentUserConfig} config - Current User Configuration */ const getAuthenticate = - ({platform, discovery}) => + config => /** * @description - Authenticate a user * @param {object} [opts] - Options * @param {object} [opts.service] - Optional service to use for authentication - * @param {object} [opts.user] - Optional user object * @param {boolean} [opts.redir] - Optional redirect flag * @returns */ @@ -174,9 +179,9 @@ const getAuthenticate = } return new Promise(async (resolve, reject) => { - spawnCurrentUser() + spawnCurrentUser(config) const opts = {redir} - const user = await snapshot() + const user = await getSnapshot(config)() const discoveryService = await getDiscoveryService(service) const refreshService = serviceOfType(user.services, "authn-refresh") let accountProofData @@ -188,7 +193,7 @@ const getAuthenticate = service: refreshService, msg: accountProofData, opts, - platform, + platform: config.platform, user, }) send(NAME, SET_CURRENT_USER, await buildUser(response)) @@ -199,7 +204,7 @@ const getAuthenticate = level: LEVELS.error, }) } finally { - return resolve(await snapshot()) + return resolve(await getSnapshot(config)()) } } else { return resolve(user) @@ -223,8 +228,8 @@ const getAuthenticate = msg: accountProofData, config: await makeConfig(discoveryService), opts, - platform, - execStrategy: discovery?.execStrategy, + platform: config.platform, + execStrategy: config.discovery?.execStrategy, user, }) @@ -236,18 +241,23 @@ const getAuthenticate = level: LEVELS.error, }) } finally { - resolve(await snapshot()) + resolve(await getSnapshot(config)()) } }) } /** - * @description - Unauthenticate a user - * @returns {void} + * @description - Factory function to get the unauthenticate method + * @param {CurrentUserConfig} config - Current User Configuration */ -function unauthenticate() { - spawnCurrentUser() - send(NAME, DEL_CURRENT_USER) +function getUnauthenticate(config) { + /** + * @description - Unauthenticate a user + */ + return function unauthenticate() { + spawnCurrentUser(config) + send(NAME, DEL_CURRENT_USER) + } } const normalizePreAuthzResponse = authz => ({ @@ -258,8 +268,12 @@ const normalizePreAuthzResponse = authz => ({ authorization: (authz || {}).authorization || [], }) +/** + * @description - Factory function to get the resolvePreAuthz method + * @param {CurrentUserConfig} config - Current User Configuration + */ const getResolvePreAuthz = - ({platform}) => + config => (authz, {user}) => { const resp = normalizePreAuthzResponse(authz) const axs = [] @@ -276,7 +290,7 @@ const getResolvePreAuthz = return execService({ service: az, msg: signable, - platform, + platform: config.platform, user, }) }, @@ -290,35 +304,36 @@ const getResolvePreAuthz = } /** - * @description - * Produces the needed authorization details for the current user to submit transactions to Flow - * It defines a signing function that connects to a user's wallet provider to produce signatures to submit transactions. + * @description - Factory function to get the authorization method * - * @param {object} opts - running options - * @param {string} opts.platform - platform that runs the function - * @param {object} [opts.discovery] - discovery options - * @param {object} account - Account object - * @returns {Promise} - Account object with signing function + * @param {CurrentUserConfig} config - Current User Configuration */ const getAuthorization = - ({platform, discovery}) => + config => + /** + * @description - Produces the needed authorization details for the current user to submit transactions to Flow + * It defines a signing function that connects to a user's wallet provider to produce signatures to submit transactions. + * + * @param {object} account - Account object + * @returns {Promise} - Account object with signing function + * */ async account => { - spawnCurrentUser() + spawnCurrentUser(config) return { ...account, tempId: "CURRENT_USER", async resolve(account, preSignable) { - const user = await getAuthenticate({platform, discovery})({redir: true}) + const user = await getAuthenticate(config)({redir: true}) const authz = serviceOfType(user.services, "authz") const preAuthz = serviceOfType(user.services, "pre-authz") if (preAuthz) - return getResolvePreAuthz({platform, discovery})( + return getResolvePreAuthz(config)( await execService({ service: preAuthz, msg: preSignable, - platform, + platform: config.platform, user, }), { @@ -342,7 +357,7 @@ const getAuthorization = opts: { includeOlderJsonRpcCall: true, }, - platform, + platform: config.platform, user, }) ) @@ -357,59 +372,59 @@ const getAuthorization = } /** - * @description - * The callback passed to subscribe will be called when the user authenticates and un-authenticates, making it easy to update the UI accordingly. - * - * @param {Function} callback - Callback function - * @returns {Function} - Unsubscribe function + * @description - Factory function to get the subscribe method + * @param {CurrentUserConfig} config - Current User Configuration */ -function subscribe(callback) { - spawnCurrentUser() - const EXIT = "@EXIT" - const self = spawn(async ctx => { - ctx.send(NAME, SUBSCRIBE) - while (1) { - const letter = await ctx.receive() - if (letter.tag === EXIT) { - ctx.send(NAME, UNSUBSCRIBE) - return +function getSubscribe(config) { + /** + * @description + * The callback passed to subscribe will be called when the user authenticates and un-authenticates, making it easy to update the UI accordingly. + * + * @param {Function} callback - Callback function + * @returns {Function} - Unsubscribe function + */ + return function subscribe(callback) { + spawnCurrentUser(config) + const EXIT = "@EXIT" + const self = spawn(async ctx => { + ctx.send(NAME, SUBSCRIBE) + while (1) { + const letter = await ctx.receive() + if (letter.tag === EXIT) { + ctx.send(NAME, UNSUBSCRIBE) + return + } + callback(letter.data) } - callback(letter.data) - } - }) - return () => send(self, EXIT) + }) + return () => send(self, EXIT) + } } /** - * @description - Gets the current user - * @returns {Promise} - User object + * @description - Factory function to get the snapshot method + * @param {CurrentUserConfig} config - Current User Configuration */ -function snapshot() { - spawnCurrentUser() - return send(NAME, SNAPSHOT, null, {expectReply: true, timeout: 0}) -} - -async function info() { - spawnCurrentUser() - const {addr} = await snapshot() - if (addr == null) throw new Error("No Flow Address for Current User") - return account(addr) +function getSnapshot(config) { + /** + * @description - Gets the current user + * @returns {Promise} - User object + */ + return function snapshot() { + spawnCurrentUser(config) + return send(NAME, SNAPSHOT, null, {expectReply: true, timeout: 0}) + } } /** - * @description - Resolves the current user as an argument + * Resolves the current user as an argument + * @param {CurrentUserConfig} config - Current User Configuration * - * @param {object} opts - running options - * @param {string} opts.platform - platform that runs the function - * @param {object} [opts.discovery] - discovery options - * @returns {Promise} */ -const getResolveArgument = - ({platform, discovery}) => - async () => { - const {addr} = await getAuthenticate({platform, discovery})() - return arg(withPrefix(addr), t.Address) - } +const getResolveArgument = config => async () => { + const {addr} = await getAuthenticate(config)() + return arg(withPrefix(addr), t.Address) +} const makeSignable = msg => { invariant(/^[0-9a-f]+$/i.test(msg), "Message must be a hex string") @@ -421,21 +436,18 @@ const makeSignable = msg => { /** * @description - Factory function to get the signUserMessage method - * @param {object} opts - running options - * @param {string} opts.platform - platform that runs the function - * @param {object} [opts.discovery] - discovery options - * @returns {function(string): Promise} + * @param {CurrentUserConfig} config - Current User Configuration */ const getSignUserMessage = - ({platform, discovery}) => + config => /** * @description - A method to use allowing the user to personally sign data via FCL Compatible Wallets/Services. * @param {string} msg - Message to sign * @returns {Promise} - Array of CompositeSignatures */ async msg => { - spawnCurrentUser() - const user = await getAuthenticate({platform, discovery})({ + spawnCurrentUser(config) + const user = await getAuthenticate(config)({ redir: true, }) @@ -450,7 +462,7 @@ const getSignUserMessage = const response = await execService({ service: signingService, msg: makeSignable(msg), - platform, + platform: config.platform, user, }) if (Array.isArray(response)) { @@ -463,45 +475,36 @@ const getSignUserMessage = } } +/** + * @typedef {object} CurrentUserConfig - Current User Configuration + * @property {string} platform - Platform + * @property {object} [discovery] - FCL Discovery Configuration + * @property {() => Promise} [getStorageProvider] - Storage Provider Getter + */ + /** * @description * Creates the Current User object * - * @param {object} opts - Configuration Options - * @param {string} opts.platform - Platform - * @param {object} [opts.discovery] - Discovery Config Resolver for additional configuration - */ -const getCurrentUser = ({platform, discovery}) => { - let currentUser = () => { - return { - authenticate: getAuthenticate({platform, discovery}), - unauthenticate, - authorization: getAuthorization({platform, discovery}), - signUserMessage: getSignUserMessage({platform, discovery}), - subscribe, - snapshot, - resolveArgument: getResolveArgument({platform, discovery}), - } + * @param {CurrentUserConfig} config - Current User Configuration + * */ +const getCurrentUser = config => { + const currentUser = { + authenticate: getAuthenticate(config), + unauthenticate: getUnauthenticate(config), + authorization: getAuthorization(config), + signUserMessage: getSignUserMessage(config), + subscribe: getSubscribe(config), + snapshot: getSnapshot(config), + resolveArgument: getResolveArgument(config), } - currentUser.authenticate = getAuthenticate({ - platform, - discovery, - }) - currentUser.unauthenticate = unauthenticate - currentUser.authorization = getAuthorization({ - platform, - discovery, - }) - currentUser.signUserMessage = getSignUserMessage({ - platform, - discovery, - }) - currentUser.subscribe = subscribe - currentUser.snapshot = snapshot - currentUser.resolveArgument = getResolveArgument({platform, discovery}) - - return currentUser + return Object.assign( + () => { + return {...currentUser} + }, + {...currentUser} + ) } export {getCurrentUser} diff --git a/packages/fcl-core/src/fcl-core.ts b/packages/fcl-core/src/fcl-core.ts index ef6579566..a031b2ca5 100644 --- a/packages/fcl-core/src/fcl-core.ts +++ b/packages/fcl-core/src/fcl-core.ts @@ -148,3 +148,5 @@ export { } from "./utils/constants" export {execStrategy} from "./current-user/exec-service" + +export type {StorageProvider} from "./utils/storage" diff --git a/packages/fcl-core/src/utils/storage.ts b/packages/fcl-core/src/utils/storage.ts new file mode 100644 index 000000000..a477becfd --- /dev/null +++ b/packages/fcl-core/src/utils/storage.ts @@ -0,0 +1,5 @@ +export type StorageProvider = { + can: boolean + get: (key: string) => Promise + put: (key: string, value: any) => Promise +} diff --git a/packages/fcl/src/fcl.ts b/packages/fcl/src/fcl.ts index 0d859d0e4..35da87833 100644 --- a/packages/fcl/src/fcl.ts +++ b/packages/fcl/src/fcl.ts @@ -63,7 +63,12 @@ export { nodeVersionInfo, } from "@onflow/fcl-core" -import {getMutate, getCurrentUser, initServiceRegistry} from "@onflow/fcl-core" +import { + getMutate, + getCurrentUser, + initServiceRegistry, + StorageProvider, +} from "@onflow/fcl-core" import {execStrategyHook} from "./discovery/exec-hook" const discoveryOpts = { @@ -74,6 +79,11 @@ export const mutate = getMutate({platform: "web", discovery: discoveryOpts}) export const currentUser = getCurrentUser({ platform: "web", discovery: discoveryOpts, + getStorageProvider: async () => { + return ( + (await config.get("fcl.storage")) || LOCAL_STORAGE + ) + }, }) export const authenticate = (opts = {}) => currentUser().authenticate(opts) @@ -88,7 +98,7 @@ export const logIn = (opts = {}) => currentUser().authenticate(opts) export const authz = currentUser().authorization import {config} from "@onflow/config" -import {getDefaultConfig, coreStrategies} from "./utils/web" +import {getDefaultConfig, coreStrategies, LOCAL_STORAGE} from "./utils/web" import {initFclWcLoader} from "./utils/walletconnect/loader" config(getDefaultConfig()) diff --git a/packages/fcl/src/utils/web/default-config.js b/packages/fcl/src/utils/web/default-config.js index 6bc0ae177..5127b7128 100644 --- a/packages/fcl/src/utils/web/default-config.js +++ b/packages/fcl/src/utils/web/default-config.js @@ -1,8 +1,5 @@ -import {LOCAL_STORAGE} from "./storage" - export const getDefaultConfig = () => { return { "discovery.wallet.method.default": "IFRAME/RPC", - "fcl.storage.default": LOCAL_STORAGE, } } diff --git a/packages/fcl/src/utils/web/storage.ts b/packages/fcl/src/utils/web/storage.ts index 5553a0778..88da9a5c9 100644 --- a/packages/fcl/src/utils/web/storage.ts +++ b/packages/fcl/src/utils/web/storage.ts @@ -1,3 +1,5 @@ +import {StorageProvider} from "@onflow/fcl-core" + const isServerSide = () => typeof window === "undefined" const safeParseJSON = (str?: string | null) => { if (str == null) return null @@ -8,22 +10,16 @@ const safeParseJSON = (str?: string | null) => { } } -export type StorageProvider = { - can: boolean - get: (key: string) => Promise - put: (key: string, value: any) => Promise -} - export const SESSION_STORAGE = { can: !isServerSide() && !!window.sessionStorage, get: async (key: string) => safeParseJSON(sessionStorage.getItem(key)), put: async (key: string, value: any) => sessionStorage.setItem(key, JSON.stringify(value)), -} +} as StorageProvider export const LOCAL_STORAGE = { can: !isServerSide() && !!window.localStorage, get: async (key: string) => safeParseJSON(localStorage.getItem(key)), put: async (key: string, value: any) => localStorage.setItem(key, JSON.stringify(value)), -} +} as StorageProvider From 77ef7c1843b7b1c590eae8b6821da4868abeb875 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Wed, 13 Nov 2024 11:44:27 -0800 Subject: [PATCH 6/8] fix react native --- .../fcl-react-native/src/fcl-react-native.ts | 8 +++++- .../src/utils/react-native/default-config.js | 17 ------------- .../src/utils/react-native/storage.ts | 25 +++++++++++++++++++ 3 files changed, 32 insertions(+), 18 deletions(-) create mode 100644 packages/fcl-react-native/src/utils/react-native/storage.ts diff --git a/packages/fcl-react-native/src/fcl-react-native.ts b/packages/fcl-react-native/src/fcl-react-native.ts index 061a07096..11357a90e 100644 --- a/packages/fcl-react-native/src/fcl-react-native.ts +++ b/packages/fcl-react-native/src/fcl-react-native.ts @@ -71,7 +71,12 @@ import { } from "@onflow/fcl-core" export const mutate = getMutate({platform: "react-native"}) -const currentUser = getCurrentUser({platform: "react-native"}) +const currentUser = getCurrentUser({ + platform: "react-native", + getStorageProvider: async () => { + return (await config().get("fcl.storage")) || getAsyncStorage() + }, +}) export {currentUser} @@ -93,6 +98,7 @@ import { useServiceDiscovery, ServiceDiscovery, } from "./utils/react-native" +import {getAsyncStorage} from "./utils/react-native/storage" config(getDefaultConfig()) diff --git a/packages/fcl-react-native/src/utils/react-native/default-config.js b/packages/fcl-react-native/src/utils/react-native/default-config.js index 8c487b152..5edeca7de 100644 --- a/packages/fcl-react-native/src/utils/react-native/default-config.js +++ b/packages/fcl-react-native/src/utils/react-native/default-config.js @@ -1,22 +1,5 @@ -import AsyncStorage from "@react-native-async-storage/async-storage" - -const getAsyncStorage = () => { - try { - const ASYNC_STORAGE = { - can: true, - get: async key => JSON.parse(await AsyncStorage.getItem(key)), - put: async (key, value) => - await AsyncStorage.setItem(key, JSON.stringify(value)), - } - return ASYNC_STORAGE - } catch (error) { - return null - } -} - export const getDefaultConfig = () => { return { "discovery.wallet.method.default": "DEEPLINK/RPC", - "fcl.storage.default": getAsyncStorage(), } } diff --git a/packages/fcl-react-native/src/utils/react-native/storage.ts b/packages/fcl-react-native/src/utils/react-native/storage.ts new file mode 100644 index 000000000..e835cf1e0 --- /dev/null +++ b/packages/fcl-react-native/src/utils/react-native/storage.ts @@ -0,0 +1,25 @@ +import AsyncStorage from "@react-native-async-storage/async-storage" + +const safeParseJSON = (str?: string | null) => { + if (str == null) return null + try { + return JSON.parse(str) + } catch (error) { + return null + } +} + +export const getAsyncStorage = () => { + try { + const ASYNC_STORAGE = { + can: true, + get: async (key: string) => + safeParseJSON(await AsyncStorage.getItem(key)), + put: async (key: string, value: any) => + await AsyncStorage.setItem(key, JSON.stringify(value)), + } + return ASYNC_STORAGE + } catch (error) { + return null + } +} From d4332d951fbfff09ee523a5727c3e1833effac54 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Wed, 13 Nov 2024 11:46:31 -0800 Subject: [PATCH 7/8] changesets --- .changeset/fresh-cows-repair.md | 5 +++++ .changeset/stupid-turkeys-hope.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/fresh-cows-repair.md create mode 100644 .changeset/stupid-turkeys-hope.md diff --git a/.changeset/fresh-cows-repair.md b/.changeset/fresh-cows-repair.md new file mode 100644 index 000000000..84a87137d --- /dev/null +++ b/.changeset/fresh-cows-repair.md @@ -0,0 +1,5 @@ +--- +"@onflow/fcl-core": minor +--- + +Add getStorageProvider to currentUser configuration diff --git a/.changeset/stupid-turkeys-hope.md b/.changeset/stupid-turkeys-hope.md new file mode 100644 index 000000000..b7f1e70f1 --- /dev/null +++ b/.changeset/stupid-turkeys-hope.md @@ -0,0 +1,5 @@ +--- +"@onflow/fcl-react-native": patch +--- + +Pass getStorageProvider to currentUser configuration From 427fb46973fe4de673baf54cec6101c74dab41fd Mon Sep 17 00:00:00 2001 From: Jordan Ribbink <17958158+jribbink@users.noreply.github.com> Date: Wed, 13 Nov 2024 12:02:55 -0800 Subject: [PATCH 8/8] Update index.js --- packages/fcl-core/src/current-user/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/fcl-core/src/current-user/index.js b/packages/fcl-core/src/current-user/index.js index ad0ca5a2b..58248ccbc 100644 --- a/packages/fcl-core/src/current-user/index.js +++ b/packages/fcl-core/src/current-user/index.js @@ -69,7 +69,6 @@ const makeHandlers = cfg => { } ctx.merge(JSON.parse(DATA)) - console.log("Storage Provider", await getStorageProvider()) const storage = await getStorageProvider() if (storage.can) { const user = await getStoredUser(storage)