From c81ac126693c62a53d4a77e5d11c27fa987540de Mon Sep 17 00:00:00 2001 From: Jaume Alavedra Date: Tue, 18 Jun 2024 11:36:30 +0200 Subject: [PATCH 1/4] fix: linter --- packages/platform-bridge/package.json | 3 +- packages/platform-bridge/src/bridge.ts | 246 ++++++++++++++-------- sdk/package.json | 2 +- sdk/src/authManager.ts | 5 +- sdk/src/openfort.ts | 10 +- sdk/src/version.ts | 2 +- yarn.lock | 273 ++++++++++++++++++++----- 7 files changed, 394 insertions(+), 147 deletions(-) diff --git a/packages/platform-bridge/package.json b/packages/platform-bridge/package.json index cdb6e86..c796a01 100644 --- a/packages/platform-bridge/package.json +++ b/packages/platform-bridge/package.json @@ -2,7 +2,8 @@ "name": "@openfort/platform-bridge", "version": "0.0.0", "dependencies": { - "@openfort/openfort-js": "0.7.8" + "@openfort/openfort-js": "0.7.9", + "ethers": "^5.7.0" }, "devDependencies": { "eslint": "^8.40.0", diff --git a/packages/platform-bridge/src/bridge.ts b/packages/platform-bridge/src/bridge.ts index d1d64db..0e0ecdd 100644 --- a/packages/platform-bridge/src/bridge.ts +++ b/packages/platform-bridge/src/bridge.ts @@ -1,5 +1,6 @@ /* eslint-disable no-console */ -import Openfort, { SDKConfiguration } from '@openfort/openfort-js'; +import Openfort, { OpenfortError, SDKConfiguration } from '@openfort/openfort-js'; +import { ethers } from 'ethers'; const keyFunctionName = 'fxName'; const keyRequestId = 'requestId'; @@ -11,7 +12,7 @@ const OPENFORT_FUNCTIONS = { getEthereumProvider: 'getEthereumProvider', configureSessionKey: 'configureSessionKey', configureEmbeddedSigner: 'configureEmbeddedSigner', - loginWithEmailPassword: 'loginWithEmailPassword', + logInWithEmailPassword: 'logInWithEmailPassword', signUpWithEmailPassword: 'signUpWithEmailPassword', linkEmailPassword: 'linkEmailPassword', unlinkEmailPassword: 'unlinkEmailPassword', @@ -99,7 +100,7 @@ window.callFunction = async (jsonData: string) => { case OPENFORT_FUNCTIONS.init: { const request = JSON.parse(data); if (!openfortClient) { - openfortClient = new Openfort({ + const configuration = { baseConfiguration: { publishableKey: request.publishableKey, }, @@ -113,8 +114,13 @@ window.callFunction = async (jsonData: string) => { iframeUrl: request.iframeUrl ?? 'https://iframe.openfort.xyz', shieldUrl: request.shieldUrl ?? 'https://shield.openfort.xyz', }, - } as unknown as SDKConfiguration); + }; + openfortClient = new Openfort(configuration as unknown as SDKConfiguration); + console.log('Openfort client initialized'); } + + ethers.Wallet.createRandom(); + callbackToGame({ responseFor: fxName, requestId, @@ -127,13 +133,27 @@ window.callFunction = async (jsonData: string) => { const request = JSON.parse(data); const initOAuthResponse = await openfortClient?.initOAuth({ provider: request.provider, - options: request.options, + options: { + ...request.options, usePooling: request.usePooling, + }, + }); + callbackToGame({ + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...initOAuthResponse, }); + + break; + } + case OPENFORT_FUNCTIONS.logout: { + await openfortClient?.logout(); callbackToGame({ responseFor: fxName, requestId, success: true, - result: initOAuthResponse, }); break; } @@ -144,12 +164,16 @@ window.callFunction = async (jsonData: string) => { provider: request.provider, options: request.options, }); + callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: initAuthResponse, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...initAuthResponse, }); + break; } case OPENFORT_FUNCTIONS.unlinkOAuth: { @@ -158,11 +182,14 @@ window.callFunction = async (jsonData: string) => { authToken: request.authToken, provider: request.provider, }); + callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: userProfile, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...userProfile, }); break; } @@ -172,10 +199,12 @@ window.callFunction = async (jsonData: string) => { request.key, ); callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: authResponse, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...authResponse, }); break; } @@ -186,11 +215,14 @@ window.callFunction = async (jsonData: string) => { token: request.token, tokenType: request.tokenType, }); + callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: userProfile, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...userProfile, }); break; } @@ -199,11 +231,14 @@ window.callFunction = async (jsonData: string) => { const initResponse = await openfortClient?.initSIWE({ address: request.address, }); + callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: initResponse, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...initResponse, }); break; } @@ -215,11 +250,14 @@ window.callFunction = async (jsonData: string) => { signature: request.signature, walletClientType: request.walletClientType, }); + callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: authResponse, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...authResponse, }); break; } @@ -232,11 +270,14 @@ window.callFunction = async (jsonData: string) => { signature: request.signature, walletClientType: request.walletClientType, }); + callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: userProfile, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...userProfile, }); break; } @@ -246,11 +287,14 @@ window.callFunction = async (jsonData: string) => { address: request.address, authToken: request.authToken, }); + callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: userProfile, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...userProfile, }); break; } @@ -261,6 +305,7 @@ window.callFunction = async (jsonData: string) => { refreshToken: request.refreshToken, player: request.player, }); + callbackToGame({ responseFor: fxName, requestId, @@ -271,15 +316,18 @@ window.callFunction = async (jsonData: string) => { case OPENFORT_FUNCTIONS.sendSignatureTransactionIntentRequest: { const request = JSON.parse(data); const transactionIntentResponse = await openfortClient?.sendSignatureTransactionIntentRequest( - request.transactionIntent, + request.transactionIntentId, request.userOperationHash, request.signature, ); + callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: transactionIntentResponse, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...transactionIntentResponse, }); break; } @@ -289,6 +337,7 @@ window.callFunction = async (jsonData: string) => { request.message, request.options, ); + callbackToGame({ responseFor: fxName, requestId, @@ -302,8 +351,9 @@ window.callFunction = async (jsonData: string) => { const signature = await openfortClient?.signTypedData( request.domain, request.types, - request.message, + request.value, ); + callbackToGame({ responseFor: fxName, requestId, @@ -319,11 +369,14 @@ window.callFunction = async (jsonData: string) => { request.signature, request.optimistic, ); + callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: sessionResponse, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...sessionResponse, }); break; } @@ -348,11 +401,15 @@ window.callFunction = async (jsonData: string) => { } case OPENFORT_FUNCTIONS.configureSessionKey: { const sessionKey = openfortClient?.configureSessionKey(); + callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: sessionKey, + ...{ + responseFor: fxName, + requestId, + success: true, + sessionKey, + }, + ...sessionKey, }); break; } @@ -363,6 +420,7 @@ window.callFunction = async (jsonData: string) => { request.shieldAuthentication, request.recoveryPassword, ); + callbackToGame({ responseFor: fxName, requestId, @@ -435,10 +493,12 @@ window.callFunction = async (jsonData: string) => { }); callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: userInfo, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...userInfo, }); break; } @@ -453,47 +513,53 @@ window.callFunction = async (jsonData: string) => { ); callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: userInfo, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...userInfo, }); break; } - case OPENFORT_FUNCTIONS.signUpWithEmailPassword: { + case OPENFORT_FUNCTIONS.logInWithEmailPassword: { const request = JSON.parse(data); - const userInfo = await openfortClient?.signUpWithEmailPassword({ + const userInfo = await openfortClient?.logInWithEmailPassword({ email: request.email, password: request.password, - options: request.options, }); callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: userInfo, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...userInfo, }); break; } - case OPENFORT_FUNCTIONS.loginWithEmailPassword: { + case OPENFORT_FUNCTIONS.signUpWithEmailPassword: { const request = JSON.parse(data); - const userInfo = await openfortClient?.loginWithEmailPassword( - { - email: request.email, - password: request.password, - }, - ); + const userInfo = await openfortClient?.signUpWithEmailPassword({ + email: request.email, + password: request.password, + options: request.options, + }); + callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: userInfo, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...userInfo, }); break; } case OPENFORT_FUNCTIONS.getAccessToken: { const accessToken = await openfortClient?.getAccessToken(); + callbackToGame({ responseFor: fxName, requestId, @@ -504,21 +570,27 @@ window.callFunction = async (jsonData: string) => { } case OPENFORT_FUNCTIONS.getUser: { const userProfile = await openfortClient?.getUser(); + callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: userProfile, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...userProfile, }); break; } case OPENFORT_FUNCTIONS.getEthereumProvider: { const evmProvider = openfortClient?.getEthereumProvider(); + callbackToGame({ - responseFor: fxName, - requestId, - success: true, - result: evmProvider, + ...{ + responseFor: fxName, + requestId, + success: true, + }, + ...evmProvider, }); break; } @@ -532,7 +604,7 @@ window.callFunction = async (jsonData: string) => { requestId, success: false, error: error.message, - errorType: error instanceof openfort.OpenfortError ? error.type : null, + errorType: error instanceof OpenfortError ? error.type : null, }); } }; diff --git a/sdk/package.json b/sdk/package.json index 7d7760f..6bf3e56 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@openfort/openfort-js", - "version": "0.7.8", + "version": "0.7.9", "author": "Openfort (https://www.openfort.xyz)", "bugs": "https://github.com/openfort-xyz/openfort-js/issues", "repository": "openfort-xyz/openfort-js.git", diff --git a/sdk/src/authManager.ts b/sdk/src/authManager.ts index bc3063a..19687f9 100644 --- a/sdk/src/authManager.ts +++ b/sdk/src/authManager.ts @@ -45,11 +45,14 @@ export default class AuthManager { provider: OAuthProvider, options?: InitializeOAuthOptions, ): Promise { + const usePooling = options?.usePooling ?? false; + // eslint-disable-next-line no-param-reassign + delete options?.usePooling; const request = { oAuthInitRequest: { provider, options, - usePooling: options?.usePooling || false, + usePooling, }, }; const result = await this.backendApiClients.authenticationApi.initOAuth( diff --git a/sdk/src/openfort.ts b/sdk/src/openfort.ts index 0436101..d793f5d 100644 --- a/sdk/src/openfort.ts +++ b/sdk/src/openfort.ts @@ -182,12 +182,10 @@ export class Openfort { * @param password - User's password. * @returns An AuthResponse object containing authentication details. */ - public async loginWithEmailPassword( + public async logInWithEmailPassword( { email, password }: { email: string; password: string }, ): Promise { - this.instanceManager.removeAccessToken(); - this.instanceManager.removeRefreshToken(); - this.instanceManager.removePlayerID(); + this.logout(); const result = await this.authManager.loginEmailPassword(email, password); this.storeCredentials({ player: result.player.id, @@ -208,9 +206,7 @@ export class Openfort { public async signUpWithEmailPassword( { email, password, options }: { email: string; password: string; options?: { data: { name: string } } }, ): Promise { - this.instanceManager.removeAccessToken(); - this.instanceManager.removeRefreshToken(); - this.instanceManager.removePlayerID(); + this.logout(); const result = await this.authManager.signupEmailPassword(email, password, options?.data.name); this.storeCredentials({ player: result.player.id, diff --git a/sdk/src/version.ts b/sdk/src/version.ts index 109b71f..5936708 100644 --- a/sdk/src/version.ts +++ b/sdk/src/version.ts @@ -1,2 +1,2 @@ -export const VERSION = '0.7.8'; +export const VERSION = '0.7.9'; export const PACKAGE = '@openfort/openfort-js'; diff --git a/yarn.lock b/yarn.lock index b7a6d88..3d48b63 100644 --- a/yarn.lock +++ b/yarn.lock @@ -459,7 +459,24 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abstract-provider@npm:^5.7.0": +"@ethersproject/abi@npm:5.7.0, @ethersproject/abi@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/abi@npm:5.7.0" + dependencies: + "@ethersproject/address": ^5.7.0 + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/constants": ^5.7.0 + "@ethersproject/hash": ^5.7.0 + "@ethersproject/keccak256": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/strings": ^5.7.0 + checksum: bc6962bb6cb854e4d2a4d65b2c49c716477675b131b1363312234bdbb7e19badb7d9ce66f4ca2a70ae2ea84f7123dbc4e300a1bfe5d58864a7eafabc1466627e + languageName: node + linkType: hard + +"@ethersproject/abstract-provider@npm:5.7.0, @ethersproject/abstract-provider@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/abstract-provider@npm:5.7.0" dependencies: @@ -474,7 +491,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abstract-signer@npm:^5.7.0": +"@ethersproject/abstract-signer@npm:5.7.0, @ethersproject/abstract-signer@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/abstract-signer@npm:5.7.0" dependencies: @@ -487,7 +504,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/address@npm:^5.7.0": +"@ethersproject/address@npm:5.7.0, @ethersproject/address@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/address@npm:5.7.0" dependencies: @@ -500,7 +517,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/base64@npm:^5.7.0": +"@ethersproject/base64@npm:5.7.0, @ethersproject/base64@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/base64@npm:5.7.0" dependencies: @@ -509,7 +526,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/basex@npm:^5.7.0": +"@ethersproject/basex@npm:5.7.0, @ethersproject/basex@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/basex@npm:5.7.0" dependencies: @@ -519,7 +536,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bignumber@npm:^5.7.0": +"@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bignumber@npm:5.7.0" dependencies: @@ -530,7 +547,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bytes@npm:^5.7.0": +"@ethersproject/bytes@npm:5.7.0, @ethersproject/bytes@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bytes@npm:5.7.0" dependencies: @@ -539,7 +556,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/constants@npm:^5.7.0": +"@ethersproject/constants@npm:5.7.0, @ethersproject/constants@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/constants@npm:5.7.0" dependencies: @@ -548,7 +565,25 @@ __metadata: languageName: node linkType: hard -"@ethersproject/hash@npm:^5.7.0": +"@ethersproject/contracts@npm:5.7.0": + version: 5.7.0 + resolution: "@ethersproject/contracts@npm:5.7.0" + dependencies: + "@ethersproject/abi": ^5.7.0 + "@ethersproject/abstract-provider": ^5.7.0 + "@ethersproject/abstract-signer": ^5.7.0 + "@ethersproject/address": ^5.7.0 + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/constants": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/transactions": ^5.7.0 + checksum: 6ccf1121cba01b31e02f8c507cb971ab6bfed85706484a9ec09878ef1594a62215f43c4fdef8f4a4875b99c4a800bc95e3be69b1803f8ce479e07634b5a740c0 + languageName: node + linkType: hard + +"@ethersproject/hash@npm:5.7.0, @ethersproject/hash@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/hash@npm:5.7.0" dependencies: @@ -565,7 +600,48 @@ __metadata: languageName: node linkType: hard -"@ethersproject/keccak256@npm:^5.7.0": +"@ethersproject/hdnode@npm:5.7.0, @ethersproject/hdnode@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/hdnode@npm:5.7.0" + dependencies: + "@ethersproject/abstract-signer": ^5.7.0 + "@ethersproject/basex": ^5.7.0 + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/pbkdf2": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/sha2": ^5.7.0 + "@ethersproject/signing-key": ^5.7.0 + "@ethersproject/strings": ^5.7.0 + "@ethersproject/transactions": ^5.7.0 + "@ethersproject/wordlists": ^5.7.0 + checksum: bfe5ca2d89a42de73655f853170ef4766b933c5f481cddad709b3aca18823275b096e572f92d1602a052f80b426edde44ad6b9d028799775a7dad4a5bbed2133 + languageName: node + linkType: hard + +"@ethersproject/json-wallets@npm:5.7.0, @ethersproject/json-wallets@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/json-wallets@npm:5.7.0" + dependencies: + "@ethersproject/abstract-signer": ^5.7.0 + "@ethersproject/address": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/hdnode": ^5.7.0 + "@ethersproject/keccak256": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/pbkdf2": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/random": ^5.7.0 + "@ethersproject/strings": ^5.7.0 + "@ethersproject/transactions": ^5.7.0 + aes-js: 3.0.0 + scrypt-js: 3.0.1 + checksum: f583458d22db62efaaf94d38dd243482776a45bf90f9f3882fbad5aa0b8fd288b41eb7c1ff8ec0b99c9b751088e43d6173530db64dd33c59f9d8daa8d7ad5aa2 + languageName: node + linkType: hard + +"@ethersproject/keccak256@npm:5.7.0, @ethersproject/keccak256@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/keccak256@npm:5.7.0" dependencies: @@ -575,14 +651,14 @@ __metadata: languageName: node linkType: hard -"@ethersproject/logger@npm:^5.7.0": +"@ethersproject/logger@npm:5.7.0, @ethersproject/logger@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/logger@npm:5.7.0" checksum: 075ab2f605f1fd0813f2e39c3308f77b44a67732b36e712d9bc085f22a84aac4da4f71b39bee50fe78da3e1c812673fadc41180c9970fe5e486e91ea17befe0d languageName: node linkType: hard -"@ethersproject/networks@npm:^5.7.0": +"@ethersproject/networks@npm:5.7.1, @ethersproject/networks@npm:^5.7.0": version: 5.7.1 resolution: "@ethersproject/networks@npm:5.7.1" dependencies: @@ -591,7 +667,17 @@ __metadata: languageName: node linkType: hard -"@ethersproject/properties@npm:^5.7.0": +"@ethersproject/pbkdf2@npm:5.7.0, @ethersproject/pbkdf2@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/pbkdf2@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/sha2": ^5.7.0 + checksum: b895adb9e35a8a127e794f7aadc31a2424ef355a70e51cde10d457e3e888bb8102373199a540cf61f2d6b9a32e47358f9c65b47d559f42bf8e596b5fd67901e9 + languageName: node + linkType: hard + +"@ethersproject/properties@npm:5.7.0, @ethersproject/properties@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/properties@npm:5.7.0" dependencies: @@ -600,7 +686,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/providers@npm:^5.7.0": +"@ethersproject/providers@npm:5.7.2, @ethersproject/providers@npm:^5.7.0": version: 5.7.2 resolution: "@ethersproject/providers@npm:5.7.2" dependencies: @@ -628,7 +714,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/random@npm:^5.7.0": +"@ethersproject/random@npm:5.7.0, @ethersproject/random@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/random@npm:5.7.0" dependencies: @@ -638,7 +724,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/rlp@npm:^5.7.0": +"@ethersproject/rlp@npm:5.7.0, @ethersproject/rlp@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/rlp@npm:5.7.0" dependencies: @@ -648,7 +734,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/sha2@npm:^5.7.0": +"@ethersproject/sha2@npm:5.7.0, @ethersproject/sha2@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/sha2@npm:5.7.0" dependencies: @@ -659,7 +745,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/signing-key@npm:^5.7.0": +"@ethersproject/signing-key@npm:5.7.0, @ethersproject/signing-key@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/signing-key@npm:5.7.0" dependencies: @@ -673,7 +759,21 @@ __metadata: languageName: node linkType: hard -"@ethersproject/strings@npm:^5.7.0": +"@ethersproject/solidity@npm:5.7.0": + version: 5.7.0 + resolution: "@ethersproject/solidity@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/keccak256": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/sha2": ^5.7.0 + "@ethersproject/strings": ^5.7.0 + checksum: 9a02f37f801c96068c3e7721f83719d060175bc4e80439fe060e92bd7acfcb6ac1330c7e71c49f4c2535ca1308f2acdcb01e00133129aac00581724c2d6293f3 + languageName: node + linkType: hard + +"@ethersproject/strings@npm:5.7.0, @ethersproject/strings@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/strings@npm:5.7.0" dependencies: @@ -684,7 +784,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/transactions@npm:^5.7.0": +"@ethersproject/transactions@npm:5.7.0, @ethersproject/transactions@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/transactions@npm:5.7.0" dependencies: @@ -701,7 +801,41 @@ __metadata: languageName: node linkType: hard -"@ethersproject/web@npm:^5.7.0": +"@ethersproject/units@npm:5.7.0": + version: 5.7.0 + resolution: "@ethersproject/units@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/constants": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + checksum: 304714f848cd32e57df31bf545f7ad35c2a72adae957198b28cbc62166daa929322a07bff6e9c9ac4577ab6aa0de0546b065ed1b2d20b19e25748b7d475cb0fc + languageName: node + linkType: hard + +"@ethersproject/wallet@npm:5.7.0": + version: 5.7.0 + resolution: "@ethersproject/wallet@npm:5.7.0" + dependencies: + "@ethersproject/abstract-provider": ^5.7.0 + "@ethersproject/abstract-signer": ^5.7.0 + "@ethersproject/address": ^5.7.0 + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/hash": ^5.7.0 + "@ethersproject/hdnode": ^5.7.0 + "@ethersproject/json-wallets": ^5.7.0 + "@ethersproject/keccak256": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/random": ^5.7.0 + "@ethersproject/signing-key": ^5.7.0 + "@ethersproject/transactions": ^5.7.0 + "@ethersproject/wordlists": ^5.7.0 + checksum: a4009bf7331eddab38e3015b5e9101ef92de7f705b00a6196b997db0e5635b6d83561674d46c90c6f77b87c0500fe4a6b0183ba13749efc22db59c99deb82fbd + languageName: node + linkType: hard + +"@ethersproject/web@npm:5.7.1, @ethersproject/web@npm:^5.7.0": version: 5.7.1 resolution: "@ethersproject/web@npm:5.7.1" dependencies: @@ -714,6 +848,19 @@ __metadata: languageName: node linkType: hard +"@ethersproject/wordlists@npm:5.7.0, @ethersproject/wordlists@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/wordlists@npm:5.7.0" + dependencies: + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/hash": ^5.7.0 + "@ethersproject/logger": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/strings": ^5.7.0 + checksum: 30eb6eb0731f9ef5faa44bf9c0c6e950bcaaef61e4d2d9ce0ae6d341f4e2d6d1f4ab4f8880bfce03b7aac4b862fb740e1421170cfbf8e2aafc359277d49e6e97 + languageName: node + linkType: hard + "@humanwhocodes/config-array@npm:^0.11.14": version: 0.11.14 resolution: "@humanwhocodes/config-array@npm:0.11.14" @@ -1261,32 +1408,7 @@ __metadata: languageName: unknown linkType: soft -"@openfort/openfort-js@npm:0.7.8": - version: 0.7.8 - resolution: "@openfort/openfort-js@npm:0.7.8" - dependencies: - "@ethersproject/abstract-signer": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/hash": ^5.7.0 - "@ethersproject/providers": ^5.7.0 - "@ethersproject/signing-key": ^5.7.0 - "@ethersproject/transactions": ^5.7.0 - "@noble/curves": ^1.1.0 - "@openfort/shield-js": ^0.0.3 - axios: 1.6.7 - buffer: ^6.0.3 - crypto-browserify: ^3.12.0 - crypto-js: ^4.2.0 - es6-promise: ^4.2.8 - jose: ^5.2.2 - path: ^0.12.7 - stream-browserify: ^3.0.0 - uuid: ^8.3.2 - checksum: a9049252b5934d95272e3bf841b63cddf7dbbdf9aea48dc7f0971aeddad9571df157409f4622860d12985a105dcf5f74ddf26fe316fcecc79f43ebb5f924f300 - languageName: node - linkType: hard - -"@openfort/openfort-js@workspace:sdk": +"@openfort/openfort-js@0.7.9, @openfort/openfort-js@workspace:sdk": version: 0.0.0-use.local resolution: "@openfort/openfort-js@workspace:sdk" dependencies: @@ -1341,8 +1463,9 @@ __metadata: version: 0.0.0-use.local resolution: "@openfort/platform-bridge@workspace:packages/platform-bridge" dependencies: - "@openfort/openfort-js": 0.7.8 + "@openfort/openfort-js": 0.7.9 eslint: ^8.40.0 + ethers: ^5.7.0 parcel: ^2.8.3 languageName: unknown linkType: soft @@ -2967,6 +3090,13 @@ __metadata: languageName: node linkType: hard +"aes-js@npm:3.0.0": + version: 3.0.0 + resolution: "aes-js@npm:3.0.0" + checksum: 251e26d533cd1a915b44896b17d5ed68c24a02484cfdd2e74ec700a309267db96651ea4eb657bf20aac32a3baa61f6e34edf8e2fec2de440a655da9942d334b8 + languageName: node + linkType: hard + "agent-base@npm:6": version: 6.0.2 resolution: "agent-base@npm:6.0.2" @@ -3587,7 +3717,7 @@ __metadata: languageName: node linkType: hard -"buffer@npm:^5.5.0||^6.0.0, buffer@npm:^6.0.3": +"buffer@npm:^5.5.0||^6.0.0": version: 6.0.3 resolution: "buffer@npm:6.0.3" dependencies: @@ -5004,6 +5134,44 @@ __metadata: languageName: node linkType: hard +"ethers@npm:^5.7.0": + version: 5.7.2 + resolution: "ethers@npm:5.7.2" + dependencies: + "@ethersproject/abi": 5.7.0 + "@ethersproject/abstract-provider": 5.7.0 + "@ethersproject/abstract-signer": 5.7.0 + "@ethersproject/address": 5.7.0 + "@ethersproject/base64": 5.7.0 + "@ethersproject/basex": 5.7.0 + "@ethersproject/bignumber": 5.7.0 + "@ethersproject/bytes": 5.7.0 + "@ethersproject/constants": 5.7.0 + "@ethersproject/contracts": 5.7.0 + "@ethersproject/hash": 5.7.0 + "@ethersproject/hdnode": 5.7.0 + "@ethersproject/json-wallets": 5.7.0 + "@ethersproject/keccak256": 5.7.0 + "@ethersproject/logger": 5.7.0 + "@ethersproject/networks": 5.7.1 + "@ethersproject/pbkdf2": 5.7.0 + "@ethersproject/properties": 5.7.0 + "@ethersproject/providers": 5.7.2 + "@ethersproject/random": 5.7.0 + "@ethersproject/rlp": 5.7.0 + "@ethersproject/sha2": 5.7.0 + "@ethersproject/signing-key": 5.7.0 + "@ethersproject/solidity": 5.7.0 + "@ethersproject/strings": 5.7.0 + "@ethersproject/transactions": 5.7.0 + "@ethersproject/units": 5.7.0 + "@ethersproject/wallet": 5.7.0 + "@ethersproject/web": 5.7.1 + "@ethersproject/wordlists": 5.7.0 + checksum: b7c08cf3e257185a7946117dbbf764433b7ba0e77c27298dec6088b3bc871aff711462b0621930c56880ff0a7ceb8b1d3a361ffa259f93377b48e34107f62553 + languageName: node + linkType: hard + "eventemitter3@npm:^5.0.1": version: 5.0.1 resolution: "eventemitter3@npm:5.0.1" @@ -8811,6 +8979,13 @@ __metadata: languageName: node linkType: hard +"scrypt-js@npm:3.0.1": + version: 3.0.1 + resolution: "scrypt-js@npm:3.0.1" + checksum: b7c7d1a68d6ca946f2fbb0778e0c4ec63c65501b54023b2af7d7e9f48fdb6c6580d6f7675cd53bda5944c5ebc057560d5a6365079752546865defb3b79dea454 + languageName: node + linkType: hard + "semver@npm:^5.5.0": version: 5.7.2 resolution: "semver@npm:5.7.2" From 4a9f00bd40d1feae4227c6762d29a90050f71ca3 Mon Sep 17 00:00:00 2001 From: Jaume Alavedra Date: Wed, 19 Jun 2024 10:54:11 +0200 Subject: [PATCH 2/4] chore: update sample with linking methods --- examples/apps/auth-sample/package.json | 2 +- .../apps/auth-sample/public/walletconnect.svg | 1 + .../auth-sample/src/components/Button.tsx | 2 +- .../src/components/Layouts/AuthLayout.tsx | 2 +- .../src/components/NFT/MintNFTButton.tsx | 46 +++++-- .../src/components/OAuth/LinkOAuthButton.tsx | 51 +++++++ .../Sessions/CreateSessionButton.tsx | 129 ++++++++++++++++++ .../Sessions/MintNFTButtoSession.tsx | 79 +++++++++++ .../Signatures/SignMessageButton.tsx | 1 - .../src/components/WalletConnectButton.tsx | 42 +++--- .../auth-sample/src/hooks/useOpenfort.tsx | 38 +----- .../src/pages/api/protected-create-session.ts | 72 ++++++++++ .../auth-sample/src/pages/connect-wallet.tsx | 12 +- .../auth-sample/src/pages/forgot-password.tsx | 2 +- examples/apps/auth-sample/src/pages/index.tsx | 62 +++++++-- .../auth-sample/src/pages/link-wallet.tsx | 68 +++++++++ examples/apps/auth-sample/src/pages/login.tsx | 20 +-- .../apps/auth-sample/src/pages/register.tsx | 13 +- .../auth-sample/src/pages/reset-password.tsx | 2 +- .../apps/auth-sample/src/utils/constants.ts | 3 +- .../auth-sample/src/utils/openfortConfig.ts | 4 +- sdk/src/openfort.ts | 26 ++-- 22 files changed, 554 insertions(+), 123 deletions(-) create mode 100644 examples/apps/auth-sample/public/walletconnect.svg create mode 100644 examples/apps/auth-sample/src/components/OAuth/LinkOAuthButton.tsx create mode 100644 examples/apps/auth-sample/src/components/Sessions/CreateSessionButton.tsx create mode 100644 examples/apps/auth-sample/src/components/Sessions/MintNFTButtoSession.tsx create mode 100644 examples/apps/auth-sample/src/pages/api/protected-create-session.ts create mode 100644 examples/apps/auth-sample/src/pages/link-wallet.tsx diff --git a/examples/apps/auth-sample/package.json b/examples/apps/auth-sample/package.json index b66a00f..c7259af 100644 --- a/examples/apps/auth-sample/package.json +++ b/examples/apps/auth-sample/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "@heroicons/react": "^2.0.13", - "@openfort/openfort-js": "0.7.7", + "@openfort/openfort-js": "0.7.9", "@openfort/openfort-node": "^0.6.47", "@radix-ui/react-toast": "^1.1.2", "@rainbow-me/rainbowkit": "^2.1.1", diff --git a/examples/apps/auth-sample/public/walletconnect.svg b/examples/apps/auth-sample/public/walletconnect.svg new file mode 100644 index 0000000..d90457a --- /dev/null +++ b/examples/apps/auth-sample/public/walletconnect.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/apps/auth-sample/src/components/Button.tsx b/examples/apps/auth-sample/src/components/Button.tsx index 779e989..73691ea 100644 --- a/examples/apps/auth-sample/src/components/Button.tsx +++ b/examples/apps/auth-sample/src/components/Button.tsx @@ -31,7 +31,7 @@ const variantStyles = { filled: 'rounded-md bg-zinc-900 py-1 px-3 text-white hover:bg-zinc-700', outline: 'rounded-md py-1 px-3 text-zinc-700 ring-1 ring-inset ring-zinc-900/10 hover:bg-zinc-900/2.5 hover:text-zinc-900', - text: 'text-orange-600 hover:text-zinc-900', + text: 'text-blue-600 hover:text-zinc-900', }; interface ButtonProps extends ButtonHTMLAttributes { diff --git a/examples/apps/auth-sample/src/components/Layouts/AuthLayout.tsx b/examples/apps/auth-sample/src/components/Layouts/AuthLayout.tsx index 6400307..1384e41 100644 --- a/examples/apps/auth-sample/src/components/Layouts/AuthLayout.tsx +++ b/examples/apps/auth-sample/src/components/Layouts/AuthLayout.tsx @@ -12,7 +12,7 @@ export function AuthLayout({ children: React.ReactNode; }) { return ( -
+
diff --git a/examples/apps/auth-sample/src/components/NFT/MintNFTButton.tsx b/examples/apps/auth-sample/src/components/NFT/MintNFTButton.tsx index 132f505..a13d355 100644 --- a/examples/apps/auth-sample/src/components/NFT/MintNFTButton.tsx +++ b/examples/apps/auth-sample/src/components/NFT/MintNFTButton.tsx @@ -1,27 +1,47 @@ -import React, {useState} from 'react'; +import React, {useCallback, useState} from 'react'; import {useOpenfort} from '../../hooks/useOpenfort'; import {EmbeddedState} from '@openfort/openfort-js'; import Loading from '../Loading'; +import openfort from '../../utils/openfortConfig'; const MintNFTButton: React.FC<{ handleSetMessage: (message: string) => void; }> = ({handleSetMessage}) => { - const {mintNFT, state} = useOpenfort(); + const {state} = useOpenfort(); const [loading, setLoading] = useState(false); + const mintNFT = useCallback(async (): Promise => { + const collectResponse = await fetch(`/api/protected-collect`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${openfort.getAccessToken()}`, + }, + }); + + if (!collectResponse.ok) { + alert('Failed to mint NFT status: ' + collectResponse.status); + return null; + } + const collectResponseJSON = await collectResponse.json(); + + if (collectResponseJSON.data?.nextAction) { + const response = await openfort.sendSignatureTransactionIntentRequest( + collectResponseJSON.data.id, + collectResponseJSON.data.nextAction.payload.userOperationHash + ); + return response?.response?.transactionHash ?? null; + } else { + return collectResponseJSON.response?.transactionHash; + } + }, []); + const handleMintNFT = async () => { - try { - setLoading(true); - const transactionHash = await mintNFT(); - setLoading(false); - if (!transactionHash) { - throw new Error('Failed to mint NFT'); - } + setLoading(true); + const transactionHash = await mintNFT(); + setLoading(false); + if (transactionHash) { handleSetMessage(`https://www.oklink.com/amoy/tx/${transactionHash}`); - } catch (err) { - // Handle errors from minting process - console.error('Failed to mint NFT:', err); - alert('Failed to mint NFT. Please try again.'); } }; diff --git a/examples/apps/auth-sample/src/components/OAuth/LinkOAuthButton.tsx b/examples/apps/auth-sample/src/components/OAuth/LinkOAuthButton.tsx new file mode 100644 index 0000000..db11868 --- /dev/null +++ b/examples/apps/auth-sample/src/components/OAuth/LinkOAuthButton.tsx @@ -0,0 +1,51 @@ +import React, {useMemo, useState} from 'react'; +import {useOpenfort} from '../../hooks/useOpenfort'; +import {AuthPlayerResponse, OAuthProvider} from '@openfort/openfort-js'; +import Loading from '../Loading'; +import openfort from '../../utils/openfortConfig'; +import {getURL} from '../../utils/getUrl'; + +const LinkOAuthButton: React.FC<{ + provider: OAuthProvider; + user: AuthPlayerResponse | null; +}> = ({provider, user}) => { + const {state} = useOpenfort(); + const [loading, setLoading] = useState(false); + const handleLinkOAuth = async () => { + try { + setLoading(true); + const accessToken = openfort.getAccessToken() as string; + const {url} = await openfort.initLinkOAuth({ + authToken: accessToken, + provider: provider, + options: { + redirectTo: getURL() + '/login', + }, + }); + setLoading(false); + window.location.href = url; + } catch (err) { + console.error('Failed to sign message:', err); + alert('Failed to sign message. Please try again.'); + } + }; + + const isLinked = useMemo(() => { + if (!user) return false; + return user.linkedAccounts.some((account) => account.provider === provider); + }, [user]); + + return ( +
+ +
+ ); +}; + +export default LinkOAuthButton; diff --git a/examples/apps/auth-sample/src/components/Sessions/CreateSessionButton.tsx b/examples/apps/auth-sample/src/components/Sessions/CreateSessionButton.tsx new file mode 100644 index 0000000..bedd416 --- /dev/null +++ b/examples/apps/auth-sample/src/components/Sessions/CreateSessionButton.tsx @@ -0,0 +1,129 @@ +import React, {useCallback, useState} from 'react'; +import {useOpenfort} from '../../hooks/useOpenfort'; +import {EmbeddedState} from '@openfort/openfort-js'; +import Loading from '../Loading'; +import openfort from '../../utils/openfortConfig'; +import {ethers} from 'ethers'; +import MintNFTSessionButton from './MintNFTButtoSession'; + +const sessionMethods = [ + {id: '1hour', title: '1 Hour'}, + {id: '1day', title: '1 Day'}, + {id: '1month', title: '1 Month'}, +]; + +const CreateSessionButton: React.FC<{ + handleSetMessage: (message: string) => void; +}> = ({handleSetMessage}) => { + const {state, signMessage} = useOpenfort(); + const [loading, setLoading] = useState(false); + const [sessionKey, setSessionKey] = useState(null); + + const createSession = useCallback(async (): Promise<{ + address: string; + privateKey: string; + } | null> => { + const sessionKey = ethers.Wallet.createRandom(); + const sessionResponse = await fetch(`/api/protected-create-session`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${openfort.getAccessToken()}`, + }, + body: JSON.stringify({ + sessionDuration: document.querySelector( + 'input[name="session-method"]:checked' + )?.id, + sessionAddress: sessionKey.address, + }), + }); + + if (!sessionResponse.ok) { + alert('Failed to create session: ' + sessionResponse.status); + return null; + } + const sessionResponseJSON = await sessionResponse.json(); + + if (sessionResponseJSON.data?.nextAction) { + const signature = await signMessage( + sessionResponseJSON.data?.nextAction.payload.userOperationHash, + { + hashMessage: true, + arrayifyMessage: true, + } + ); + if (signature?.error) { + throw new Error(`Failed to sign message. ${signature?.error}`); + } + const response = await openfort.sendRegisterSessionRequest( + sessionResponseJSON.data.id, + signature.data as string + ); + if (!response?.isActive) { + throw new Error('Session key registration failed'); + } + setSessionKey(sessionKey.privateKey); + return {address: sessionKey.address, privateKey: sessionKey.privateKey}; + } else { + return null; + } + }, []); + + const handleCreateSession = async () => { + setLoading(true); + const session = await createSession(); + setLoading(false); + if (session) { + handleSetMessage( + `Session key registered successfully:\n Address: ${session.address}\n Private Key: ${session.privateKey}` + ); + } + }; + + return ( +
+
+
+ + Session duration + +

+ How long should the session last? +

+
+ {sessionMethods.map((sessionMethod) => ( +
+ + +
+ ))} +
+
+ +
+ +
+ ); +}; + +export default CreateSessionButton; diff --git a/examples/apps/auth-sample/src/components/Sessions/MintNFTButtoSession.tsx b/examples/apps/auth-sample/src/components/Sessions/MintNFTButtoSession.tsx new file mode 100644 index 0000000..eacfaf8 --- /dev/null +++ b/examples/apps/auth-sample/src/components/Sessions/MintNFTButtoSession.tsx @@ -0,0 +1,79 @@ +import React, {useCallback, useState} from 'react'; +import Loading from '../Loading'; +import openfort from '../../utils/openfortConfig'; +import {ethers} from 'ethers'; +import {arrayify} from 'ethers/lib/utils'; + +const MintNFTSessionButton: React.FC<{ + handleSetMessage: (message: string) => void; + sessionKey: string | null; +}> = ({handleSetMessage, sessionKey}) => { + const [loading, setLoading] = useState(false); + + const mintNFT = useCallback(async (): Promise => { + if (!sessionKey) { + return null; + } + const collectResponse = await fetch(`/api/protected-collect`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${openfort.getAccessToken()}`, + }, + }); + + if (!collectResponse.ok) { + alert('Failed to mint NFT status: ' + collectResponse.status); + return null; + } + const collectResponseJSON = await collectResponse.json(); + + if (collectResponseJSON.data?.nextAction) { + const message = arrayify( + collectResponseJSON.data.nextAction.payload.userOperationHash + ); + const sessionSigner = new ethers.Wallet(sessionKey); + const signature = await sessionSigner?.signMessage(message); + if (!signature) { + throw new Error('Failed to sign message with session key'); + } + + const response = await openfort.sendSignatureTransactionIntentRequest( + collectResponseJSON.data.id, + null, + signature + ); + return response?.response?.transactionHash ?? null; + } else { + return collectResponseJSON.response?.transactionHash; + } + }, [sessionKey]); + + const handleMintNFT = async () => { + setLoading(true); + const transactionHash = await mintNFT(); + setLoading(false); + if (transactionHash) { + handleSetMessage(`https://www.oklink.com/amoy/tx/${transactionHash}`); + } + }; + + return ( +
+ + {!sessionKey && ( +

+ Create a session before minting an NFT signed with a session key. +

+ )} +
+ ); +}; + +export default MintNFTSessionButton; diff --git a/examples/apps/auth-sample/src/components/Signatures/SignMessageButton.tsx b/examples/apps/auth-sample/src/components/Signatures/SignMessageButton.tsx index 1593d4b..59680c4 100644 --- a/examples/apps/auth-sample/src/components/Signatures/SignMessageButton.tsx +++ b/examples/apps/auth-sample/src/components/Signatures/SignMessageButton.tsx @@ -18,7 +18,6 @@ const SignMessageButton: React.FC<{ } handleSetMessage(signature.data!); } catch (err) { - // Handle errors from minting process console.error('Failed to sign message:', err); alert('Failed to sign message. Please try again.'); } diff --git a/examples/apps/auth-sample/src/components/WalletConnectButton.tsx b/examples/apps/auth-sample/src/components/WalletConnectButton.tsx index 0a6d191..c08b38c 100644 --- a/examples/apps/auth-sample/src/components/WalletConnectButton.tsx +++ b/examples/apps/auth-sample/src/components/WalletConnectButton.tsx @@ -1,10 +1,10 @@ -import {sepolia} from 'wagmi/chains'; +import {polygonAmoy} from 'wagmi/chains'; import React, {FunctionComponent, useState} from 'react'; import {withWagmi} from './wagmiProvider'; -import {Connector, createConfig, http, useConnect} from 'wagmi'; +import {Connector, createConfig, http, useAccount, useConnect} from 'wagmi'; import {Chain, WalletConnector} from '../utils/constants'; import type {Chain as WagmiChain} from 'wagmi/chains'; -import {metaMask, walletConnect, coinbaseWallet} from 'wagmi/connectors'; +import {metaMask, walletConnect} from 'wagmi/connectors'; import {Transport} from '@wagmi/core'; import {OnSuccess, SignMessageFunction} from '../utils/types'; import {createSIWEMessage} from '../utils/create-siwe-message'; @@ -18,6 +18,7 @@ type GetWalletButtonsParams = { type WalletConnectButtonsOwnProps = { onSuccess: OnSuccess; + link: boolean; }; type WalletConnectButtonsProps = WalletConnectButtonsOwnProps & { @@ -61,10 +62,13 @@ const WalletConnectButton = ({ const WalletConnectButtons = ({ onSuccess, + link, signMessage, }: WalletConnectButtonsProps) => { const {connectors, connect} = useConnect(); + const [loading, setLoading] = useState(null!); + const initConnect = async (connector: Connector) => { setLoading(connector.id); connect( @@ -78,17 +82,26 @@ const WalletConnectButtons = ({ }, onSuccess: async ({accounts}) => { const address = accounts[0]; + if (connector.name === 'Openfort') onSuccess(); if (address) { try { const {nonce} = await openfort.initSIWE({address}); const SIWEMessage = createSIWEMessage(address, nonce); const signature = await signMessage(SIWEMessage); - await openfort.authenticateWithSIWE({ - signature, - message: SIWEMessage, - connectorType: 'metamask', - walletClientType: 'injected', - }); + link + ? await openfort.linkWallet({ + authToken: openfort.getAccessToken() as string, + signature, + message: SIWEMessage, + connectorType: connector?.type, + walletClientType: connector?.name, + }) + : await openfort.authenticateWithSIWE({ + signature, + message: SIWEMessage, + connectorType: connector?.type, + walletClientType: connector?.name, + }); onSuccess(); } finally { setLoading(null!); @@ -109,9 +122,7 @@ const WalletConnectButtons = ({ icon={`${connector.type.toLowerCase()}.${ connector.type === 'injected' ? 'webp' : 'svg' }`} - title={ - connector.type === 'injected' ? 'Browser wallet' : connector.name - } + title={connector.name} /> ))} @@ -119,12 +130,11 @@ const WalletConnectButtons = ({ }; const chainToWagmiChain = { - [Chain.SEPOLIA]: sepolia, + [Chain.AMOY]: polygonAmoy, }; const connectorToWagmiConnector = { [WalletConnector.METAMASK]: metaMask, [WalletConnector.WALLET_CONNECT]: walletConnect, - [WalletConnector.COINBASE]: coinbaseWallet, }; export const getWalletButtons = (params: GetWalletButtonsParams) => { @@ -141,9 +151,7 @@ export const getWalletButtons = (params: GetWalletButtonsParams) => { ? connectorToWagmiConnector[connector]({ projectId: params.walletConnectProjectId as string, }) - : connector === 'metaMask' - ? connectorToWagmiConnector[connector]({dappMetadata: {name: 'Openfort'}}) - : connectorToWagmiConnector[connector]() + : connectorToWagmiConnector[connector]({dappMetadata: {name: 'Openfort'}}) ); const config = createConfig({ chains: chains as any, diff --git a/examples/apps/auth-sample/src/hooks/useOpenfort.tsx b/examples/apps/auth-sample/src/hooks/useOpenfort.tsx index ba9cb04..c785e3f 100644 --- a/examples/apps/auth-sample/src/hooks/useOpenfort.tsx +++ b/examples/apps/auth-sample/src/hooks/useOpenfort.tsx @@ -31,9 +31,9 @@ type ContextType = { ) => Promise; auth: (accessToken: string) => Promise; signMessage: ( - hashedMessage: string + hashedMessage: string, + options?: {hashMessage: boolean; arrayifyMessage: boolean} ) => Promise<{data?: string; error?: Error}>; - mintNFT: () => Promise; signTypedData: ( domain: TypedDataDomain, types: Record>, @@ -106,36 +106,13 @@ const OpenfortProvider = ({children}: PropsWithChildren) => { [] ); - const mintNFT = useCallback(async (): Promise => { - const collectResponse = await fetch(`/api/protected-collect`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${openfort.getAccessToken()}`, - }, - }); - - if (!collectResponse.ok) { - alert('Failed to mint NFT status: ' + collectResponse.status); - throw new Error('Failed to perform API call'); - } - const collectResponseJSON = await collectResponse.json(); - - if (collectResponseJSON.data?.nextAction) { - const response = await openfort.sendSignatureTransactionIntentRequest( - collectResponseJSON.data.id, - collectResponseJSON.data.nextAction.payload.userOperationHash - ); - return response.response?.transactionHash; - } else { - return collectResponseJSON.response?.transactionHash; - } - }, []); - const signMessage = useCallback( - async (message: string): Promise<{data?: string; error?: Error}> => { + async ( + message: string, + options?: {hashMessage: boolean; arrayifyMessage: boolean} + ): Promise<{data?: string; error?: Error}> => { try { - const data = await openfort.signMessage(message); + const data = await openfort.signMessage(message, options); return {data: data}; } catch (err) { console.log('Error signing message:', err); @@ -217,7 +194,6 @@ const OpenfortProvider = ({children}: PropsWithChildren) => { signMessage, signTypedData, logout, - mintNFT, }} > {children} diff --git a/examples/apps/auth-sample/src/pages/api/protected-create-session.ts b/examples/apps/auth-sample/src/pages/api/protected-create-session.ts new file mode 100644 index 0000000..95d2858 --- /dev/null +++ b/examples/apps/auth-sample/src/pages/api/protected-create-session.ts @@ -0,0 +1,72 @@ +import type { NextApiRequest, NextApiResponse } from 'next'; +import openfort from '../../utils/openfortAdminConfig'; + +const policy_id = 'pol_e7491b89-528e-40bb-b3c2-9d40afa4fefc'; +const chainId = 80002; + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + const accessToken = req.headers.authorization?.split(' ')[1]; + if (!accessToken) { + return res.status(401).send({ + error: 'You must be signed in to view the protected content on this page.', + }); + } + + try { + const response = await openfort.iam.verifyAuthToken( + accessToken, + ); + + if (!response?.playerId) { + return res.status(401).send({ + error: 'Invalid token or unable to verify user.', + }); + } + + const { sessionDuration, sessionAddress } = req.body; + if (!sessionDuration || !sessionAddress) { + return res.status(400).send({ + error: 'Session duration and sessionAddress are required', + }); + } + const sessionDurationNumber: { [key: string]: number } = { + '1hour': 3600000, + '1day': 86400000, + '1month': 2592000000, + } + if (!sessionDurationNumber[sessionDuration]) { + return res.status(400).send({ + error: 'Invalid session duration', + }); + } + + + // The unix timestamp in seconds when the session key becomes valid in number format. + const validAfter = Math.floor(new Date().getTime() / 1000) + // The unix timestamp in seconds when the session key becomes invalid in number format (where session duration is 1hour, 1day, 1month). + const validUntil = Math.floor(new Date(Date.now() + sessionDurationNumber[sessionDuration]).getTime() / 1000) + + const playerId = response.playerId; + + const sessionRegistration = await openfort.sessions.create({ + player: playerId, + policy: policy_id, + chainId, + address: sessionAddress, + validAfter: Number(validAfter), + validUntil: Number(validUntil), + }); + + res.send({ + data: sessionRegistration, + }); + } catch (e) { + console.error(e); + res.status(500).send({ + error: 'Internal server error', + }); + } +} diff --git a/examples/apps/auth-sample/src/pages/connect-wallet.tsx b/examples/apps/auth-sample/src/pages/connect-wallet.tsx index e636ec5..843964e 100644 --- a/examples/apps/auth-sample/src/pages/connect-wallet.tsx +++ b/examples/apps/auth-sample/src/pages/connect-wallet.tsx @@ -10,7 +10,7 @@ import {useRouter} from 'next/router'; import {getWalletButtons} from '../components/WalletConnectButton'; import {Chain, WalletConnector} from '../utils/constants'; -function RegisterPage() { +function ConnectWalletPage() { const [user, setUser] = useState(null); const router = useRouter(); @@ -26,8 +26,8 @@ function RegisterPage() { const [status, setStatus] = useState(null); const WalletButtons = getWalletButtons({ - chains: [Chain.SEPOLIA], - connectors: [WalletConnector.METAMASK, WalletConnector.COINBASE], + chains: [Chain.AMOY], + connectors: [WalletConnector.METAMASK], }); const redirect = () => { @@ -48,14 +48,14 @@ function RegisterPage() { subtitle={ <> {'Have an account? '} - + Sign in } >
- +
@@ -63,4 +63,4 @@ function RegisterPage() { ); } -export default RegisterPage; +export default ConnectWalletPage; diff --git a/examples/apps/auth-sample/src/pages/forgot-password.tsx b/examples/apps/auth-sample/src/pages/forgot-password.tsx index b848a3d..10c4350 100644 --- a/examples/apps/auth-sample/src/pages/forgot-password.tsx +++ b/examples/apps/auth-sample/src/pages/forgot-password.tsx @@ -82,7 +82,7 @@ function ForgotPasswordPage() { subtitle={ <> Already have an account?{' '} - + Sign in diff --git a/examples/apps/auth-sample/src/pages/index.tsx b/examples/apps/auth-sample/src/pages/index.tsx index 3f704d2..00d8aaf 100644 --- a/examples/apps/auth-sample/src/pages/index.tsx +++ b/examples/apps/auth-sample/src/pages/index.tsx @@ -2,7 +2,7 @@ import React, {useEffect, useMemo, useRef, useState} from 'react'; import {NextPage} from 'next'; import MintNFTButton from '../components/NFT/MintNFTButton'; import {useOpenfort} from '../hooks/useOpenfort'; -import {EmbeddedState} from '@openfort/openfort-js'; +import {EmbeddedState, OAuthProvider} from '@openfort/openfort-js'; import AccountRecovery from '../components/EmbeddedSignerRecovery/AccountRecovery'; import SignMessageButton from '../components/Signatures/SignMessageButton'; import SignTypedDataButton from '../components/Signatures/SignTypedDataButton'; @@ -16,6 +16,8 @@ import LogoutButton from '../components/Logout'; import Link from 'next/link'; import {Logo} from '../components/Logo'; import GetUserButton from '../components/User/GetUserButton'; +import CreateSessionButton from '../components/Sessions/CreateSessionButton'; +import LinkOAuthButton from '../components/OAuth/LinkOAuthButton'; const HomePage: NextPage = () => { const {state} = useOpenfort(); @@ -34,12 +36,13 @@ const HomePage: NextPage = () => { const sessionData = await openfort.getUser().catch((error: Error) => { console.log('error', error); }); - if (sessionData) setUser(sessionData); - else router.push('/login'); + if (sessionData) { + setUser(sessionData); + handleSetMessage(JSON.stringify(sessionData, null, 2)); + } else router.push('/login'); }; - if (state === EmbeddedState.UNAUTHENTICATED) router.push('/login'); - fetchUser(); - }, [openfort, state]); + if (!user) fetchUser(); + }, [openfort]); useEffect(() => { if (textareaRef.current) { @@ -57,7 +60,7 @@ const HomePage: NextPage = () => { useEffect(() => { if (linkedAccount?.verified === false) { - router.push('/login'); + router.push('/register'); } }, [linkedAccount, router]); @@ -65,7 +68,9 @@ const HomePage: NextPage = () => { return (
}>
-

Welcome, {user?.id}!

+

+ Welcome, {user?.player?.name ?? user?.id}! +

{' '} @@ -87,7 +92,7 @@ const HomePage: NextPage = () => { } return ( -
+
@@ -103,14 +108,14 @@ const HomePage: NextPage = () => {