diff --git a/src/inventory/maliks-majik.ts b/src/inventory/maliks-majik.ts index bf73c04..bc070d6 100644 --- a/src/inventory/maliks-majik.ts +++ b/src/inventory/maliks-majik.ts @@ -32,10 +32,13 @@ export const ABILITY_MYSTIC_CRYPT = 'create-mystic-crypt'; export const ABILITY_JOIN_CIRCLE = 'join-summoning-circle'; const joinMasterDjinnCircle = joinCircle(ABILITY_EQUIP_MAJIK, async ({ signature }) => { - if (MAJIK_CARDS.find((mjq: string) => mjq === signature.etherAddress)) + const masterDjinn = MAJIK_CARDS.find((mjq: string) => mjq === signature.etherAddress); + console.log('Joining ', masterDjinn, ' master Djinn circle? ', !!masterDjinn); + + if (!masterDjinn) return { isValid: false, - message: 'Jubmoji is not a Master Djinn', + message: signature.etherAddress + ' Jubmoji is not a Master Djinn', }; return { diff --git a/src/utils/api.ts b/src/utils/api.ts index ab5cdf2..e538684 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -14,7 +14,7 @@ import { } from 'utils/config'; import { getSpellBook } from 'utils/zkpid'; import { debug, track } from './logging'; -import { JubJubSigResponse, SummoningProofs } from 'types/GameMechanics'; +import { JubJubSigResponse } from 'types/GameMechanics'; import { signWithId } from './zkpid'; // TODO persist cache to local storage for better offline use once internet connection lost? @@ -160,13 +160,13 @@ export const MU_ACTIVATE_JINNI = ` `; export const MU_JOIN_CIRCLE = ` - mutation join_circle( + mutation jinni_join_circle( $verification: SignedRequest!, $majik_msg: String!, $player_id: String!, $jinni_id: String ) { - join_circle( + jinni_join_circle( verification: $verification, majik_msg: $majik_msg, player_id: $player_id, @@ -451,6 +451,7 @@ export const joinCircle = // customized per flow checks e.g. master djinn before saving to API if (checkValidity) { const { isValid, message: validityMsg } = await checkValidity(validityArgs); + console.log('is valid custom check ', isValid, validityMsg); if (!isValid) { track(userFlow, { spell: userFlow, @@ -465,21 +466,23 @@ export const joinCircle = } } - const circles = await getStorage(PROOF_MALIKS_MAJIK_SLOT); - if (circles?.[result.etherAddress]) { - track(userFlow, { - spell: userFlow, - signature: result.signature.ether, - jubmoji: result.etherAddress, - messageToSign, - circle: jinniId, - activityType: 'already-joined', - }); - return false; - } + // const circles = await getStorage(PROOF_MALIKS_MAJIK_SLOT); + // if (circles?.[result.etherAddress]) { + // track(userFlow, { + // spell: userFlow, + // signature: result.signature.ether, + // jubmoji: result.etherAddress, + // messageToSign, + // circle: jinniId, + // activityType: 'already-joined', + // }); + // return false; + // } // also used to create circle. If no circle for card that signs then generates with current player as the owner - const response = await qu({ mutation: MU_JOIN_CIRCLE })({ + const response = await qu>({ + mutation: MU_JOIN_CIRCLE, + })({ majik_msg: result.signature.ether, player_id: playerId, jinni_id: jinniId, // TODO only null on create circle @@ -507,14 +510,15 @@ export const joinCircle = true, ); + const jid = response.data.jinni_join_circle; track(userFlow, { spell: userFlow, summoner: result.etherAddress, - circle: jinniId, + circle: jid, activityType: 'success', }); - return response ? true : false; + return jid ? true : false; } catch (e) { console.log('Mani:Jinni:MysticCrypt:ERROR --', e); throw e; diff --git a/src/utils/config.ts b/src/utils/config.ts index 25b7b92..8d38fde 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -24,7 +24,8 @@ import { ItemIds } from 'types/GameMechanics'; export const HOME_CONFIG_STORAGE_SLOT = 'home.widgets'; export const MALIKS_MAJIK_CARD = '0x46C79830a421038E75853eD0b476Ae17bFeC289A'; // angel -export const MAJIK_CARDS = [MALIKS_MAJIK_CARD]; +export const MAJIK_JESTER = '0x36B957C0c5953c79ff665743E447491F9154F4EA'; // yarrrgg +export const MAJIK_CARDS = [MALIKS_MAJIK_CARD, MAJIK_JESTER]; // cross provider analytics eventrs export const TRACK_PERMS_REQUESTED = 'PERMISSIONS_REQUESTED'; diff --git a/src/utils/zkpid.android.ts b/src/utils/zkpid.android.ts index 7871db2..ee7ad87 100644 --- a/src/utils/zkpid.android.ts +++ b/src/utils/zkpid.android.ts @@ -11,7 +11,7 @@ import { JubjubSignature } from 'types/GameMechanics.js'; * */ export const signWithId = async (id: string | Identity): Promise => { - console.log('sign anon id with majik', id, typeof id); + console.log('utils:zkpid:android:sign anon id with majik', id, typeof id); // https://github.com/cursive-team/jubmoji.quest/blob/2f0ccb203d432c40d2f26410d6a695f2de4feddc/apps/jubmoji-quest/src/components/modals/ForegroundTapModal.tsx#L2 try { const msg = typeof id === 'string' ? id : id._commitment; diff --git a/src/utils/zkpid.ios.ts b/src/utils/zkpid.ios.ts index 1a4bb8c..4a44b00 100644 --- a/src/utils/zkpid.ios.ts +++ b/src/utils/zkpid.ios.ts @@ -11,7 +11,7 @@ import { JubjubSignature } from 'types/GameMechanics'; * */ export const signWithId = async (id: string | Identity): Promise => { - console.log('sign anon id with majik', id, typeof id); + console.log('utils:zkpid:ios:sign anon id with majik', id, typeof id); // https://github.com/cursive-team/jubmoji.quest/blob/2f0ccb203d432c40d2f26410d6a695f2de4feddc/apps/jubmoji-quest/src/components/modals/ForegroundTapModal.tsx#L2 try { const msg = typeof id === 'string' ? id : id._commitment; diff --git a/src/utils/zkpid.web.ts b/src/utils/zkpid.web.ts index 61fc6cf..5c1b51d 100644 --- a/src/utils/zkpid.web.ts +++ b/src/utils/zkpid.web.ts @@ -4,13 +4,56 @@ import { execHaloCmdWeb } from '@arx-research/libhalo/api/web.js'; import { debug } from './logging'; import { JubJubSigResponse } from 'types/GameMechanics'; +import { ethers } from 'ethers'; + +interface BrowserWalletSignResult { + signature: string; + address: string; +} + +const signWithBrowserWallet = async (message: string): Promise => { + try { + if (typeof window.ethereum !== 'undefined') { + await window.ethereum.request({ method: 'eth_requestAccounts' }); + const provider = new ethers.providers.Web3Provider(window.ethereum); + const signer = provider.getSigner(); + const signature = await signer.signMessage(message); + const address = await signer.getAddress(); + return { signature, address }; + } else { + console.warn('No Ethereum wallet detected'); + return null; + } + } catch (error) { + console.error('Error signing with browser wallet:', error); + return null; + } +}; + +const fallbackToWalletSignature = async ( + id: string | Identity, +): Promise => { + const msg = typeof id === 'string' ? id : id._commitment; + const result = await signWithBrowserWallet(msg); + console.log('utils:zkpid:web:wallet fallback', result); + + if (result) { + return { + signature: { + ether: result.signature, + }, + etherAddress: result.address, + }; + } + return null; +}; /** TODO figure out return types from HaLo lib * + add callback fn to handle succ/err * */ export const signWithId = async (id: string | Identity): Promise => { - console.log('sign anon id with majik', id, typeof id); + console.log('utils:zkpid:web:sign anon id with majik', id, typeof id); // https://github.com/cursive-team/jubmoji.quest/blob/2f0ccb203d432c40d2f26410d6a695f2de4feddc/apps/jubmoji-quest/src/components/modals/ForegroundTapModal.tsx#L2 try { const msg = typeof id === 'string' ? id : id._commitment; @@ -20,6 +63,7 @@ export const signWithId = async (id: string | Identity): Promise { if (cause === 'init') { @@ -35,11 +79,17 @@ export const signWithId = async (id: string | Identity): Promise